2009-02-25 9 views
37

अगर मैं सी # में एक कक्षा लिखता हूं जो IDISposable लागू करता है, तो मेरे लिए किसी भी अप्रबंधित संसाधनों को मुक्त करने के लिए.NET में निपटान (बूल निपटान) को ओवरराइड करने का क्या मतलब है?

public void Dispose(){ ... } 

को लागू करने के लिए पर्याप्त क्यों नहीं है?

protected virtual void Dispose(bool disposing){ ... } 

हमेशा जरूरी है, कभी-कभी जरूरी है, या कुछ और पूरी तरह से?

+0

मेरी कक्षा में मेरे पास केवल अप्रबंधित संसाधन हैं जिन्हें सफाई की आवश्यकता है और मैं स्थाई आभासी शून्य निपटान (बूल डिस्पोजेक्ट) के साथ आईडीस्पोजेबल लागू कर रहा हूं क्योंकि स्थिर विश्लेषण इसे करने के लिए मजबूर करता है। मेरे मामले में "निपटान" पैरामीटर का कोई उपयोग नहीं है क्योंकि मैं फाइनलाइज़र और एक ही काम करने का निपटान करना चाहता हूं। – AksharRoop

उत्तर

28

यह कड़ाई से जरूरी नहीं है। यह अनुशंसित डिस्पोजेबल पैटर्न का हिस्सा है। यदि आपने इस पर फ्रेमवर्क डिज़ाइन दिशानिर्देश अनुभाग नहीं पढ़ा है (पहले संस्करण में 9.3, दूसरे संस्करण में माफी माफ नहीं है) तो आपको चाहिए। Try this link

यह डिस्पोजेबल सफाई और finalizable के बीच भेद के लिए उपयोगी है कचरा-संग्रह-है-trashing-मुझे।

आपको इसे इस तरह से करने की ज़रूरत नहीं है, लेकिन आपको इसे पढ़ना चाहिए और समझना चाहिए कि इसे अनावश्यक के रूप में छूटने से पहले इसकी सिफारिश क्यों की जाती है।

+3

"आईडीस्पोजेबल: जो आपकी मां ने कभी भी संसाधन डीलोकेशन के बारे में आपको बताया नहीं है" का लिंक बहुत नीचे है, इसलिए मैं इसे यहां डुप्लिकेट करूंगा: http://www.codeproject.com/KB/dotnet/IDisposable.aspx –

+0

FYI ब्लूबाइट्स सॉफ्टवेयर से ऊपर पहला लिंक अब टूटा हुआ है। – codenheim

+0

@mrjoltcola धन्यवाद, एमएसडीएन लिंक में अपडेट किया गया है (लेकिन वे थोड़ा सा क्षणिक भी हो सकते हैं) –

3

bool निपटान के साथ अतिरिक्त विधि कहीं एक रूपरेखा डिजाइन दिशानिर्देश से बाहर आया। यह केवल एक पैटर्न है जिससे आपकी कक्षा को निपटान विधि को अपवाद फेंकने के बिना कई बार बुलाया जा सके। यह बिल्कुल जरूरी नहीं है। तकनीकी रूप से आप इसे निपटान विधि में कर सकते हैं।

13

डिस्पोजेबल पैटर्न के बारे में MSFT डॉक्स में पूर्वाग्रह का एक सा नहीं है। एक प्रकार है कि IDisposable

  • लागू करता है आप एक finalizer मिल गया है के क्षेत्र

    1. आप मिल गया है: दो कारण आप IDisposable को लागू करना चाहिए रहे हैं।

    केस 1 अधिकांश कोड में काफी आम है। केस 2 माइक्रोसॉफ्ट लिखने वाले कोड में काफी आम है, वे वे थे जो अप्रबंधित संसाधनों के आसपास प्रबंधित रैपर लिखे थे, जिन्हें अंतिम रूप देने की आवश्यकता है। लेकिन आपके कोड में बहुत असामान्य होना चाहिए। आखिरकार, आपके पास उन सभी अच्छे .NET कक्षाएं आपके लिए गंदा काम करने के लिए मिल गई हैं। आपको बस अपने निपटान() विधियों को कॉल करना होगा।

    केवल मामला 2 डिस्पोजेबल पैटर्न की आवश्यकता है। माइक्रोसॉफ्ट को इसका बहुत उपयोग करने की जरूरत है। आपको बस सबसे अधिक सरल निपटान() की आवश्यकता होगी।

  • +0

    मेरी कक्षा में मैंने केवल उन्बंधित संसाधनों की आवश्यकता है जिन्हें सफाई की आवश्यकता है और मैं संरक्षित आभासी शून्य निपटान (बूल निपटान) के साथ स्थिरता को कार्यान्वित कर रहा हूं विश्लेषण इसे करने के लिए मजबूर करता है। मेरे मामले में "निपटान" पैरामीटर का कोई उपयोग नहीं है क्योंकि मैं फाइनलाइज़र और एक ही काम करने का निपटान करना चाहता हूं। – AksharRoop

    +0

    सुनिश्चित नहीं है कि यह टिप्पणी व्यक्त करने के लिए क्या है। आप शायद इसे गलत कर रहे हैं, सेफहैंडल और/या सेफबफर रैपर कक्षाओं का उपयोग करें। गंभीर फाइनलाइज़र अच्छे हैं। बुलेट पर वापस 1. –

    +0

    ठीक है, तो मेरा मूल प्रश्न यह है कि जब मूल्य सही होता है तो मूल्य अलग होता है (बूल निपटान) और मूल्य गलत है। के लिए इस्तेमाल पैरामीटर का निपटान क्या है? – AksharRoop

    41

    एक अंतिम आभासी विधि और मूल निपटान विधि के "सीलिंग" का परिचय पूर्ण आधार है, जिसमें सभी आधार शामिल हैं।

    जब तक आप अप्रबंधित संसाधनों पर प्रत्यक्ष हैंडल (almostnever होना चाहिए जो) यदि आप एक finalizer की आवश्यकता नहीं है।

    यदि आप अपनी कक्षा को सील करते हैं (और जहां भी संभव हो सीलिंग कक्षाओं पर मेरे विचार शायद अब तक ज्ञात हैं - design for inheritance or prohibit it) वर्चुअल विधि को पेश करने में कोई बात नहीं है।

    मुझे याद नहीं आया कि मैंने आखिरी बार IDisposable को "जटिल" तरीके से लागू किया था, जो इसे सबसे स्पष्ट तरीके से बना रहा था, उदाहरण के लिएनोट करने के लिए

    public void Dispose() 
    { 
        somethingElse.Dispose(); 
    } 
    

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

    +0

    बहुत बढ़िया स्पष्टीकरण - और एक राहत! –

    +0

    एफवाईआई, ब्लूबाइट टूटा हुआ आपका लिंक –

    +0

    @ हैमिशस्मिथ: फिक्स्ड, धन्यवाद। (ब्लॉग चले गए थे।) –

    5

    अन्य महान उत्तर देने के लिए इसके अलावा, आप इन लेखों की जांच करना चाहते हो सकता है:

    +2

    पहले लेख में अभी भी सरल निपटान मामले में 'निपटान' संपत्ति शामिल है, जो व्यर्थ है। वास्तव में सरल मामला यह है कि जॉन ने अपने उदाहरण में 'वर्चुअल' कीवर्ड के संभावित जोड़े के साथ क्या रखा। – piers7

    1

    बस क्या दूसरों है पर विस्तार करने के लिए ने कहा: यह सिर्फ इतना नहीं है कि आप को 'जटिल निपटान' की आवश्यकता नहीं है, तो यह है कि आप वास्तव में इसे प्रदर्शन प्रदर्शन के लिए नहीं चाहते हैं बेटों।

    यदि आप 'जटिल निपटान' मार्ग पर जाते हैं, और एक अंतिमकर्ता को लागू करते हैं, और फिर स्पष्ट रूप से अपनी वस्तु का निपटान करना भूल जाते हैं, तो आपकी वस्तु (और इसके संदर्भ में कुछ भी) एक अतिरिक्त जीसी पीढ़ी को वास्तव में निपटाए जाने से पहले जीवित रहेगा (क्योंकि इसमें सीएलआर के लिए फाइनलाइज़र को कॉल करने के लिए एक और बार लटका देना)। यह सिर्फ अधिक मेमोरी दबाव का कारण बनता है जिसकी आपको आवश्यकता नहीं है। इसके अतिरिक्त, ऑब्जेक्ट्स के पूरे ढेर पर फाइनलाइज़र को कॉल करना एक गैर-मामूली लागत है।

    तो इससे बचें, जब तक कि आप (या आपके व्युत्पन्न प्रकार) में अप्रबंधित संसाधन न हों।

    ओह, और जब हम क्षेत्र में हैं: आपकी कक्षा के तरीकों को दूसरों से घटनाओं को संभालने के तरीके को आपकी कक्षा के निपटारे के बाद बुलाए जाने के चेहरे में 'सुरक्षित' होना चाहिए। सरलता है कि कक्षा का निपटारा होने पर केवल नो-ऑप करें। देखें http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx

    1

    एक चीज जो आपको देता है वह आपको निपटान() को अंतिम रूप देने से संबंधित करने की क्षमता है, और अभी भी अप्रबंधित संसाधनों को साफ करता है।

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

    एक ही विधि में निपटान और अंतिमकर्ता कॉल दोनों को प्रेषित करने से आप अपने शट डाउन कोड को साझा कर सकते हैं, जबकि बूलियन पैरामीटर आपको प्रबंधित क्लीनअप को छोड़ने की अनुमति देता है यदि आपके पास कोई है।

    इसके अलावा, विधि के वर्चुअल-नेस, विरासतकर्ताओं को अपने स्वयं के क्लीनअप कोड को जोड़ने का एक आसान तरीका प्रदान करता है, अनजाने में आपके कॉल को बुलाए जाने का जोखिम कम नहीं होता है।

    1

    एक वर्ग IDisposable.Dispose() लागू करता है और एक व्युत्पन्न वर्ग अतिरिक्त तर्क जोड़ने की जरूरत है, तो उस वर्ग Dispose विधि है कि व्युत्पन्न वर्ग कर सकते हैं श्रृंखला के लिए किसी तरह का पर्दाफाश करना होगा। चूंकि कुछ कक्षाएं IDisposable.Dispose() को सार्वजनिक Dispose() विधि के बिना कार्यान्वित कर सकती हैं, इसलिए IDisposable के सभी कार्यान्वयन में protectedprotected होगा, भले ही उनके पास Dispose विधि हो या नहीं।ज्यादातर मामलों में, bool तर्क वास्तव में सार्थक नहीं है लेकिन protected virtual Dispose(bool) को बनाने के लिए डमी तर्क के रूप में सोचा जाना चाहिए, हो सकता है कि हो सकता है कि हो सकता है कि हो सकता है-शायद-नहीं-सार्वजनिक-सार्वजनिक Dispose()

    कक्षाएं जो protected virtual Dispose(bool) का उपयोग नहीं करती हैं, उन्हें अवशोषण से अलग फैशन में उनके क्लीनअप तर्क को संभालने के लिए व्युत्पन्न कक्षाओं की आवश्यकता होगी। सी ++/सीएलआई जैसी कुछ भाषाएं जो केवल IDisposable कार्यान्वयन को बढ़ाने के लिए सुसज्जित हैं जो उस सम्मेलन का पालन करती हैं, गैर-मानक कार्यान्वयन से कक्षाएं प्राप्त करने में असमर्थ हो सकती हैं।

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