गैर-निपटान स्थानीय लोगों के बारे में CA2000 चेतावनी से बचने के लिए सामान्य पैटर्न एक अस्थायी चर का उपयोग करना है जो कुछ भी गलत होने पर निपटाया जाता है, जैसे:

Foo f = null;
try
{
    f = new Foo();
    Foo result = f;
    f = null;
    return result;
}
finally
{
    if (f != null)
    {
        f.Dispose();
    }
}

थोड़ा वर्बोज़, लेकिन यह काम करता है, और यह समझ में आता है। लेकिन कोई उस पैटर्न को जंजीर वाले कंस्ट्रक्टरों पर कैसे लागू करता है, जैसे:

public HomeController ( IDataRepository db )
{
    this.repo = db ?? new SqlDataRepository();
}

public HomeController ( )
    : this(new SqlDataRepository())
{
}

यह कोड दो CA2000 चेतावनियाँ फेंक रहा है, एक प्रति कंस्ट्रक्टर। पहला मैं अस्थायी चर पैटर्न का उपयोग करने से छुटकारा पा सकता हूं। यह बहुत कष्टप्रद है, क्योंकि स्थानीय के निर्माण के बाद उसके दायरे से बाहर जाने का कोई रास्ता नहीं दिखता है, लेकिन इससे पहले कि इसे सदस्य क्षेत्र को सौंपा जाए, जो बाद में साफ हो जाता है। इसलिए मुझे नहीं पता कि सीए की समस्या क्या है, लेकिन कम से कम मुझे पता है कि इसे ठीक करने के लिए क्या करना चाहिए।

लेकिन, जहां तक ​​​​मैं समझ सकता हूं, कोशिश/आखिरकार पेश करने के लिए दूसरा कन्स्ट्रक्टर कॉल लिखने का कोई वैकल्पिक तरीका नहीं है। जिस फ़ील्ड को असाइन किया जा रहा है वह केवल-पढ़ने के लिए है, इसलिए इसे एक कंस्ट्रक्टर में सेट किया जाना चाहिए। और सी # आपको कंस्ट्रक्टर बॉडी से पहले कहीं भी जंजीर कंस्ट्रक्टर्स को कॉल करने की अनुमति नहीं देगा। और, दोनों में से, दूसरी चेतावनी वास्तव में अधिक वैध है - जंजीर वाले कंस्ट्रक्टर को कॉल (सिद्धांत रूप में, यदि यह कोई वास्तविक कार्य करता है) एक अपवाद फेंक सकता है और नव निर्मित पैरामीटर को छोड़ सकता है।

बेशक, मैं हमेशा इस संदेश को दबा सकता हूं (जिसे सीए 2000 की बहुत आवश्यकता है), लेकिन अगर समस्या को खत्म करने का कोई वास्तविक तरीका है तो मैं ऐसा करना पसंद करूंगा।

4
Michael Edenfield 19 जुलाई 2011, 21:14
आईएमओ, यह एक सीए बग है।
 – 
nawfal
16 मार्च 2018, 21:26

1 उत्तर

सबसे बढ़िया उत्तर

मैं IDataRepository तर्क लेने वाले निर्माता पर CA2000 उल्लंघन को दोबारा नहीं कर सकता। इसे देखते हुए, इस तथ्य के साथ कि आप दोनों कंस्ट्रक्टरों के लिए समान "डिफ़ॉल्ट" का उपयोग करते हैं, नमूना परिदृश्य के लिए CA2000 समस्याओं से बचने वाला सबसे सरल परिवर्तन है:

public HomeController(IDataRepository db)
{
    this.repo = db ?? new SqlDataRepository();
}

public HomeController()
    : this(null)
{
}

जाहिर है, यह बहुत अच्छी तरह से काम नहीं करेगा यदि आपका पहला कंस्ट्रक्टर शून्य पैरामीटर मान को स्वीकार नहीं करता है। यदि ऐसा होता और आप संबंधित फ़ील्ड को केवल एक ही स्थान पर सेट करने के विचार से पूरी तरह से विवाहित हैं, तो आपके पास अभी भी CA2000 से बचने के विकल्प होंगे, जैसे कि थोड़ा होशियार निजी कंस्ट्रक्टर। उदाहरण:

public HomeController(IDataRepository db)
    : this(() => db, false)
{
    if (db == null)
    {
        throw new ArgumentNullException("db");
    }
}

public HomeController()
    : this(() => new SqlDataRepository(), true)
{
}

private HomeController(Func<IDataRepository> repositoryRetriever, bool disposeOnFailure)
{
    IDataRepository repository = repositoryRetriever.Invoke();
    try
    {
        this.repo = repository;
    }
    catch
    {
        if (disposeOnFailure)
        {
            repository.Dispose();
        }

        throw;
    }
}

व्यक्तिगत रूप से, मुझे लगता है कि उपरोक्त बहुत बुरा हैक है, विशेष रूप से यह देखते हुए कि इसमें संभावित समस्या से बचने के हितों में कोड जटिलता और रनटाइम अपवाद की संभावना दोनों को बढ़ाना शामिल है जो पहले स्थान पर बहुत गंभीर नहीं था। मेरी सिफारिश होगी कि इस प्रकार के संभावित CA2000 उल्लंघनों को केवल तब तक अनदेखा किया जाए जब तक कि निम्नलिखित दोनों सत्य न हों:

  1. ऑब्जेक्ट की तात्कालिकता और उस विधि के अंत के बीच एक गैर-दुर्घटनाग्रस्त अपवाद का एक वास्तविक मौका है जिसमें इसे किसी फ़ील्ड को सौंपा गया है।
  2. अनाथ उदाहरण को निपटाने में विफल रहने के परिणाम काफी गंभीर होते हैं (जैसे: किसी फ़ाइल को लॉक छोड़ना)।
2
Nicole Calinoiu 19 जुलाई 2011, 23:47
क्या repositoryRetriever को try ब्लॉक के अंदर नहीं बुलाया जाना चाहिए?
 – 
ChrisWue
11 मार्च 2012, 02:52
@ChrisWue: नहीं, इसकी कोई आवश्यकता नहीं है। जब तक लक्ष्य चर को डिस्पोजेबल मान असाइन नहीं किया जाता है, तब तक आप इसका निपटान नहीं कर सकते क्योंकि आपके पास इसका कोई संदर्भ नहीं है।
 – 
Nicole Calinoiu
11 मार्च 2012, 03:34