2012-01-16 16 views
9

IDisposable ऑब्जेक्ट पर स्पष्ट रूप से Dispose() पर कॉल करने के खिलाफ नियम बनाना उचित है?क्या निपटान() को स्पष्ट कॉल से बचना उचित है?

क्या ऐसे कोई मामले हैं जहां using कथन ठीक से IDisposable ऑब्जेक्ट साफ़ नहीं किया जा सकता है?

+0

जितना मैं कचरा कलेक्टर को मेरे लिए अपनी याददाश्त का प्रबंधन करना चाहता हूं, मेरे पास निपटान() को कॉल करने के खिलाफ कोई आरक्षण नहीं है यदि मेरे पास ऐसा करने का कोई कारण है। –

+4

@ सैमआईम: कॉलिंग निपटान का बिंदु संसाधन को मुक्त करना है कि मेमोरी मैनेजर * आपके लिए मुफ्त नहीं है *। निपटान स्पष्ट रूप से * गैर स्मृति * संसाधनों के प्रबंधन के बारे में है, इसलिए मेमोरी मैनेजर को इसमें बिल्कुल न लाएं। –

उत्तर

11

IDisposable ऑब्जेक्ट पर स्पष्ट रूप से Dispose() पर कॉल करने के खिलाफ नियम बनाना उचित है?

सं

देखते हैं किसी भी मामलों में जहां एक using बयान ठीक से एक IDisposable वस्तु सुनिश्चित नहीं कर सकते ऊपर साफ किया जाता है?

निश्चित रूप से ऐसे मामले हैं जहां using का उपयोग आपके लिए किसी ऑब्जेक्ट को निपटाने के लिए नहीं करना है। उदाहरण के लिए, सभी मामलों जहां ऑब्जेक्ट का वांछित जीवनकाल using कथन वाली विधि के किसी विशेष सक्रियण से बंधे नहीं है।

उदाहरण के लिए एक डिस्पोजेबल ऑब्जेक्ट पर विचार करें जो किसी अन्य डिस्पोजेबल ऑब्जेक्ट के "प्रबंधन को लेता है"। "बाहरी" ऑब्जेक्ट को using ब्लॉक द्वारा निपटाया जा सकता है, लेकिन बाहरी वस्तु के निजी क्षेत्र में संग्रहीत "आंतरिक" ऑब्जेक्ट को Dispose() पर एक स्पष्ट कॉल के बिना निपटाने के लिए कैसे किया जा सकता है?

+0

एक अच्छा, साफ जवाब! मुझे लगता है कि सवाल सी ++ के लिए मेरे सेवानिवृत्त प्यार से बाहर हो गया है और आरएआईआई व्यक्त करने के लिए इसका साफ वाक्यविन्यास है। –

+1

@NickStrupat: "क्लीन सिंटैक्स" से आपका मतलब है "वर्ण'} 'कोड निष्पादित करने का कारण बनता है "। यह एक "साफ" वाक्यविन्यास नहीं है, यह एक खतरनाक रूप से भ्रामक वाक्यविन्यास है। चरित्र जो एक व्याख्यात्मक दायरे का निर्धारण करता है उसे निष्पादन योग्य कोड * से संबद्ध नहीं किया जाना चाहिए; तथ्य यह है कि यह सी ++ में है सी ++ की डिजाइन त्रुटियों में से एक है। यह मेरे लिए एक रहस्य है कि क्यों कोई सोचता है कि यह एक अच्छा विचार है; अगर मेरा संसाधन क्लीनअप कोड महत्वपूर्ण है तो मैं कोड में * स्पष्ट * होना चाहता हूं ताकि मैं * * * * समझ सकूं * और * डीबग * कर सकूं। यदि यह महत्वपूर्ण है, तो इसे छिपाएं नहीं। –

+1

@EricLippert - शैतान के वकील को खेलने के लिए, '}' जो सी # में 'उपयोग' ब्लॉक को बंद करता है, तर्कसंगत रूप से निष्पादित करने के लिए कोड का कारण बनता है। क्या आपको लगता है कि यह "खतरनाक रूप से भ्रामक" वाक्यविन्यास है, या इसे बहाने के लिए पर्याप्त ब्लॉक की शुरुआत में "उपयोग" की उपस्थिति है? – kvb

5

कुछ मामलों में Dispose पर एक स्पष्ट कॉल से बचने के लिए बस संभव नहीं है और अभी भी उचित अर्थशास्त्र बनाए रखें। उदाहरण के लिए IDisposable ऑब्जेक्ट्स पर विचार करें जिनके पास फ़ील्ड IDisposable भी है। वे Dispose को सुस्पष्ट रूप से कॉल क्षेत्र

class Container : IDisposable { 
    private readonly IDisposable _field; 

    public void Dipose() { 

    // Don't want a using here. 
    _field.Dispose(); 
    } 
} 
+1

अच्छी तरह से, आप अभी भी निपटान को ट्रिगर करने के लिए एक प्रयोग ब्लॉक का उपयोग कर सकते हैं ... लेकिन यह अजीब होगा क्योंकि यह ऑब्जेक्ट के पूरे जीवनकाल से मेल नहीं खाएगा, बस इसकी मृत्यु। 'उपयोग' नियंत्रण अभिव्यक्ति को ऑब्जेक्ट बनाने की आवश्यकता नहीं है, इसे केवल एक चर निर्दिष्ट करना होगा। –

+0

@BenVoigt हाँ आप * उपयोग कर सकते हैं। हालांकि यह थोड़ी अधिक ओवरकिल होगी; 0 ​​ – JaredPar

1

निपटान के लिए हमें चाहिए एक डिस्पोजेबल प्रकार के उदाहरण बनाने की लागत बहुत अधिक है (उदाहरण के लिए एक प्रकार है जो एक दूरस्थ कनेक्शन समाहित), तो आपको उदाहरणों पुन: उपयोग करने amortize कर सकते हैं कीमत। उस स्थिति में using उपयोगी नहीं होगा और आपको किसी बिंदु पर Dispose पर कॉल करना होगा।

1

मैं इस तरह के नियम के खिलाफ वोट दूंगा, यदि आपके पास ऐसी ऑब्जेक्ट है जो आप कई फ़ंक्शन कॉल में कई बार उपयोग करना चाहते हैं, तो एक कथन का विवरण उस ऑब्जेक्ट के निपटारे को मजबूर करेगा, अगली बार जब आप इसका उपयोग करना चाहते हैं, तो आपके पास पुन: प्रारंभ करने के लिए ...

2

using कथन (जो आखिर में Dispose के साथ अंततः ब्लॉक में बुलाया गया है) के लिए प्रयास करने के लिए शॉर्टेंड है) परिदृश्यों के लिए जहां आप संसाधन प्राप्त करते हैं, इसका उपयोग करते हैं, फिर इसे एक ही विधि में निपटान करते हैं। यदि आपके पास संसाधन का इतना रैखिक उपयोग नहीं है (उदा। इसका उपयोग विधियों में विभाजित है) तो आपको Dispose पर कॉल करना होगा।

3

एक प्राकृतिक धारणा है कि आप हमेशा एक वस्तु पर Dispose कॉल कर सकते हैं, और यह है कि क्या राज्य वस्तु है की परवाह किए बिना वस्तु के संसाधनों को साफ करेंगे,

में। यह प्राकृतिक धारणा हमेशा एक सही धारणा नहीं है।

एक उदाहरण WCF client proxies. के साथ है।

var serviceClient = new sandbox.SandboxServiceClient(); 
serviceClient.HelloWorld(name); 
if(serviceClient.State == CommunicationState.Faulted) 
{ 
    serviceClient.Abort(); 
} 
else 
{ 
    serviceClient.Dispose(); 
} 

using वाक्य रचना में स्विच करना असुरक्षित कोड में परिणाम होगा:

using (var serviceClient = new sandbox.SandboxServiceClient()) 
{ 
    serviceClient.HelloWorld(name); 
} // Here An exception will be thrown if the channel has faulted 

आप तर्क दे सकता है (जैसा कि हम सभी कर

प्रॉक्सी जीवन का प्रबंधन करने का सही तरीका इस प्रकार है) कि यह डब्ल्यूसीएफ का एक दोषपूर्ण पहलू पहलू है, लेकिन प्रोग्रामिंग की वास्तविकता यह है कि हमें कभी-कभी हमारे द्वारा उपयोग किए जाने वाले ढांचे को समायोजित करने के लिए हमारी शैली को संशोधित करना होता है। यहां एक उदाहरण दिया गया है जहां स्पष्ट Dispose के खिलाफ एक कंबल नियम लागू नहीं हो सकता है, भले ही ऑब्जेक्ट का जीवनकाल एक फ़ंक्शन कॉल में निहित हो।

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