2012-06-28 14 views
14

बुला रहा है आम तौर पर जब आप एक निजी सदस्य निपटान, आप निम्न कर सकता है:FxCop बताओ किसी अन्य विधि का निपटान

public void Dispose() { 
    var localInst = this.privateMember; 
    if (localInst != null) { 
     localInst.Dispose(); 
    } 
} 

स्थानीय काम करने के उद्देश्य से एक रेस स्थिति, जहां एक और धागा निजी निर्धारित करना चाहेंगे से बचने के लिए है शून्य जांच के बाद सदस्य शून्य हो। इस मामले में, मुझे कोई परवाह नहीं है कि Dispose को उदाहरण पर दो बार बुलाया जाता है।

मैं इस पैटर्न हर समय उपयोग करती हैं इसलिए मैंने लिखा यह करने के लिए एक विस्तार विधि:

public static void SafeDispose(this IDisposable disposable) 
{ 
    if (disposable != null) 
    { 
     // We also know disposable cannot be null here, 
     // even if the original reference is null. 
     disposable.Dispose(); 
    } 
} 

और अब मेरी कक्षा में, मैं सिर्फ यह कर सकते हैं:

public void Dispose() { 
    this.privateMember.SafeDispose(); 
} 

समस्या है, FxCop को पता नहीं है कि मैं यह कर रहा हूं और यह मुझे हर मामले में CA2000: Dispose objects before losing scope चेतावनी देता है।

मैं इस नियम को बंद नहीं करना चाहता हूं और मैं हर मामले को दबाना नहीं चाहता हूं। क्या FxCop को संकेत देने का कोई तरीका है कि यह विधि Dispose के बराबर है जहां तक ​​यह चिंतित है?

+3

आप नमूना कहते हैं 'this.privateMember.Dispose()'। क्या आपका कोड वास्तव में 'this.privateMember.SafeDispose() 'कहता है? –

उत्तर

8

संक्षिप्त उत्तर है: वहाँ संकेत है कि वस्तु कहीं निपटारा किया जा रहा है कोई रास्ता नहीं है।

थोड़ा सा प्रतिबिंबक (या डॉटपीक-आईएनजी, या जो कुछ भी) बताता है क्यों।

FxCop C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop में है। (अपने ओएस/वीएस संस्करण कॉम्बो के अनुसार तदनुसार समायोजित करें।) नियम Rules उपनिर्देशिका में हैं।

मुख्य FxCop फ़ोल्डर में, खुली

  • Microsoft.VisualStudio.CodeAnalysis.dll
  • Microsoft.VisualStudio.CodeAnalysis.Phoenix.dll
  • phx.dll

Rules फ़ोल्डर में, खुली DataflowRules.dll

DataflowRules.dllPhoenix.CodeAnalysis.DataflowRules.DisposeObjectsBeforeLosingScope पर खोजें। वह वास्तविक वर्ग है जो मूल्यांकन करता है।

वहां कोड को देखते हुए, आप अपने प्रश्न के संबंध में रुचि के दो चीजें देख सकते हैं।

  1. यह का उपयोग करता है एक साझा सेवा SharedNeedsDisposedAnalysis कहा जाता है।
  2. यह FunctionBodyRule से निकला है।

पहला आइटम दिलचस्प है क्योंकि SharedNeedsDisposedAnalysis क्या निर्धारित करता है जो प्रतीकों Dispose() कहा जाता है की जरूरत है। यह बहुत अच्छी तरह से है, यह निर्धारित करने के लिए कोड के माध्यम से "चलना" कर रहा है कि क्या निपटान की आवश्यकता है और वास्तव में क्या निपटान किया जाता है। यह बाद में उपयोग के लिए उन चीजों की एक तालिका रखता है।

दूसरे मद दिलचस्प है क्योंकि FunctionBodyRule नियम एक भी समारोह के शरीर का मूल्यांकन। अन्य नियम प्रकार हैं, जैसे FunctionCallRule जो फ़ंक्शन कॉल सदस्यों (उदा। ProvideCorrectArgumentsToFormattingMethods) जैसी चीजों का मूल्यांकन करते हैं।

बिंदु है, कि SharedNeedsDisposedAnalysis सेवा में संभावित "याद आती है" जहां यह अपने विधि के माध्यम से recursing जा नहीं हो सकता है देखने के लिए है कि चीजें वास्तव में निपटारा किया जा रहा है और FunctionBodyRule की सीमा समारोह शरीर से परे नहीं जा रहा के बीच, यह सिर्फ है अपना विस्तार नहीं पकड़ रहा है।

यह वह जगह है इसी कारण "गार्ड कार्यों" इससे पहले कि आप इसका इस्तेमाल करते हैं जैसे कभी नहीं तर्क मान्य के रूप में देखा हो - FxCop अभी भी अशक्त के लिए तर्क की जाँच करने के आपको बता देंगे, भले ही है कि "गार्ड समारोह" क्या कर रहा है है ।

आपके पास मूल रूप से दो विकल्प हैं।

  1. समस्याएं बहिष्कृत करें या नियम बंद करें। ऐसा कोई तरीका नहीं है जो आप चाहते हैं।
  2. एक कस्टम/व्युत्पन्न नियम बनाएं जो विस्तार विधियों को समझ सके। डिफ़ॉल्ट नियम के स्थान पर अपने कस्टम नियम का उपयोग करें।

लिखा कस्टम FxCop अपने आप नियम होने के बाद, मैं तुम्हें पता है मुझे मिल गया ... गैर तुच्छ दूँगा। यदि आप उस सड़क पर जाते हैं, जबकि दुनिया में सिफारिश नई फीनिक्स इंजन नियम शैली का उपयोग करना है (यही वर्तमान DisposeObjectsBeforeLosingScope उपयोग करता है), मुझे पुराने/मानक FxCop SDK नियमों को समझना आसान लगता है (FxCopSdk.dll देखें मुख्य FxCop फ़ोल्डर)। परावर्तक यह पता लगाने में एक बड़ी मदद करेंगे कि ऐसा कैसे करें क्योंकि इसमें बहुत अधिक शून्य दस्तावेज़ है। उन उदाहरणों को देखने के लिए Rules फ़ोल्डर में अन्य असेंबली में देखें।

+1

Acutally, CA1062 द्वारा गार्ड फ़ंक्शंस की पहचान के लिए एक तंत्र है: ValidatedNotNullAttribute नामक एक विशेषता के साथ सजावट। दुर्भाग्य से, स्वभाव नियमों के लिए कोई समान तंत्र नहीं है। –

+0

धन्यवाद ट्रैविस! क्या आप कस्टम नियम लिखने के लिए एक अच्छी गाइड जानते हैं? मेरे पास मेरे निर्माण के हिस्से के रूप में fxcop चल रहा है और मैं यह सुनिश्चित करना चाहता हूं कि यह स्रोत से नियम लोड कर सकता है (प्रोग्राम फ़ाइलों से नहीं)। – Haacked

+0

मैंने पाया [यह] (http://www.binarycoder.net/fxcop/pdf/fxcop.pdf) श्वेत पत्र बहुत उपयोगी है। – riezebosch

1

मैं किसी भी तरह से FxCop विशेषज्ञ नहीं हूं, लेकिन this question को SuppressMessage का उपयोग करने के बारे में जवाब देता है? मुझे नहीं पता कि SuppressMessage विशेषता के साथ आपकी सुरक्षित डिज़ाइन विधि को सजाने के कारण FxCop उस संदेश को उन तरीकों के विश्लेषण पर दबाने का कारण बनता है, लेकिन ऐसा लगता है कि यह एक शॉट के लायक है।

नीचे वाक्य रचना पर विश्वास न करें, लेकिन कुछ की तरह:

[SuppressMessage("Microsoft.Design", "CA2000:Dispose objects before losing scope", Justification = "We just log the exception and return an HTTP code")] 
public static void SafeDispose(this IDisposable disposable) 
0

यह कोड विश्लेषण नियम एक समस्याग्रस्त है, सभी कारणों से ट्रैविस ने रेखांकित किया है। ऐसा लगता है कि किसी भी "नए" ऑपरेशन को कतारबद्ध करना है, और जब तक निपटान कॉल बंद न हो, सीए 2000 ट्रिगर्स।

इसके बजाय नए का उपयोग करने का, शरीर में इस के साथ एक विधि कॉल:

MyDisposableClass result; 
MyDisposableClass temp = null; 
try 
{ 
    temp = new MyDisposableClass(); 
    //do any initialization here 
    result = temp; 
    temp = null; 
} 
finally 
{ 
    if (temp != null) temp.Dispose(); 
} 
return result; 

क्या करता है वस्तु के कारण निपटान के लिए पहुँच योग्य नहीं होने के लिए प्रारंभ की किसी भी संभावना को दूर है। आपके मामले में, जब आप "नया" निजी सदस्य बनाते हैं, तो आप इसे उस विधि के भीतर करेंगे जो उपर्युक्त विधि जैसा दिखता है। इस पैटर्न का उपयोग करने के बाद, आप अभी भी सही निपटान के लिए ज़िम्मेदार हैं, और आपकी विस्तार विधि उस शून्य जांच को सामान्य करने का एक शानदार तरीका है।

मुझे पता चला है कि आप अभी भी IDISposables को पास करते हुए सीए 2000 से बच सकते हैं और जो भी आप चाहते हैं उसके साथ कर सकते हैं - जब तक आप ऊपर की तरह किसी विधि के भीतर उन्हें सही तरीके से नए बनाते हैं। इसे आज़माएं और मुझे बताएं कि यह आपके लिए काम करता है या नहीं। शुभकामनाएं, और अच्छा सवाल!

इस नियम (यह एक सहित) के लिए अन्य सुधारों को यहां दिए गए हैं: CA2000: Dispose objects before losing scope (Microsoft)

संबंधित मुद्दे