यदि कोई आईडीसोपयोगी वस्तु संदर्भ निपटाता है तो कोई कैसे बताता है?


85

क्या एक विधि, या कुछ अन्य हल्के-फुल्के तरीके हैं, यह जांचने के लिए कि क्या कोई संदर्भ किसी विवादित वस्तु के लिए है?

पुनश्च - यह सिर्फ एक उत्सुकता है (नींद अच्छी तरह से, उत्पादन कोड में नहीं)। हां, मुझे पता है कि मैं ObjectDisposedExceptionऑब्जेक्ट के एक सदस्य तक पहुंचने की कोशिश कर रहा हूं ।


11
पता नहीं। यह उत्सुक लगता है कि वहाँ bool IsDisposed { get; }पर एक घोषणा नहीं है System.IDisposable
निकोडेमस 13

3
@ निकोडेमस 13: यह Disposeविधि किसी भी और सभी संसाधनों को जारी करने के लिए एक वस्तु को निर्देशित करती है जो उसने अधिग्रहित की है लेकिन अभी तक जारी नहीं की गई है। यदि कोई वस्तु कभी संसाधन नहीं रखती है, तो इसकी Disposeविधि में आम तौर पर कुछ भी करने की आवश्यकता नहीं होगी; यदि प्रकार की घोषणा करता है तो void IDisposable.Dispose() {};यह अन्यथा IDisposableप्रति-उदाहरण ओवरहेड के साथ अनदेखा कर सकता है । एक IsDisposedसंपत्ति जो किसी भी Disposeकॉल के बाद सच होने की उम्मीद थी , उसे कई प्रकार के हर उदाहरण में एक अन्यथा अनावश्यक बूलियन ध्वज जोड़ने की आवश्यकता होगी जो अन्यथा अनदेखा कर सकते हैं Dispose
सुपरकैट

1
लेकिन, जब भी आप किसी ऐसी विधि पर कॉल करते हैं IDisposable, जो लागू होती है , तो आप कैसे जांच सकते हैं कि क्या यह पहले निपटाया गया है? यह मानने के बजाय कि यह अपवाद नहीं है? या किसी भी तरह आप जीवनकाल का प्रबंधन करने के लिए हैं ताकि आपको हमेशा पता चले कि यह निपटाया गया है या नहीं?
निकोडेमस

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

WeakReferenceयहां प्रासंगिक लगता है। यह वास्तव में एक IDipose'd डिटेक्टर नहीं है, लेकिन यह आपको बताता है कि यह GC'd
Malachi

जवाबों:


47

आईडीआई-यूपीआई पैटर्न के डिफ़ॉल्ट कार्यान्वयन का समर्थन नहीं करता है


41

System.Windows.Forms.Controlएक IsDisposedसंपत्ति है जो कहा जाता है के बाद सच करने के लिए सेट Dispose()है । अपनी खुद की आईडीसिसोपयोगी वस्तुओं में आप आसानी से एक समान संपत्ति बना सकते हैं।


ओपी यह देखना चाह रहा था कि क्या वस्तुओं पर पहले से ही समान संपत्ति है जो वह नहीं बना रहा है। यह हमारे द्वारा बनाई गई वस्तुओं के लिए एक अच्छा विचार होगा, लेकिन .NET में अधिकांश डिस्पोजेबल कक्षाएं इस सम्मेलन का पालन नहीं करती हैं। डांडिकस का जवाब सही है।
क्रिलगर

2
@krillgar, ओपी के सवाल में कुछ भी नहीं है जो आपके दावे का समर्थन करता है।
रेयान लुंडी

18

इसमें कुछ भी नहीं बनाया गया है। आपको एक IsDisposed बूलियन संपत्ति को उजागर करने की आवश्यकता होगी जो एक आंतरिक निपटाने वाले झंडे को दर्शाती है।

public class SimpleCleanup : IDisposable
{
    private bool disposed = false;

    public bool IsDisposed
    {
       get
       {
          return disposed;
       }
    }

    public SimpleCleanup()
    {
        this.handle = /*...*/;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
               // free only managed resources here
            }

            // free unmanaged resources here
            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}

BTW, यदि कोई इस पैटर्न का उपयोग करना शुरू करता है, तो यह एक नए इंटरफ़ेस ( IDisposablePlusया जो भी) को इनहेरिट करता है IDisposableऔर जिसमें शामिल है , को परिभाषित करने में मदद करता है bool IsDisposed { get; }। इससे यह जानना आसान हो जाता है कि आपकी कौन सी IDisposableवस्तु समर्थन करती है IsDisposed
टूलमेकरसेव

मुझे नहीं लगता कि आप C # काम करने के कारण एक इंटरफ़ेस प्राप्त कर सकते हैं। एक बृहदान्त्र के बाद एक इंटरफ़ेस रखने से यह विरासत में मिलता है। मुझे उम्मीद है कि यह दूसरे पर इंटरफ़ेस लागू करेगा।
मूसा

9

यदि यह आपकी कक्षा नहीं है और यह एक IsDisposed संपत्ति (या कुछ समान - नाम सिर्फ एक सम्मेलन है) प्रदान नहीं करता है, तो आपके पास जानने का कोई तरीका नहीं है।

लेकिन अगर यह आपकी कक्षा है और आप विहित आईडीआईएसओप्रयोग कार्यान्वयन का पालन ​​कर रहे हैं , तो बस एक संपत्ति के रूप में _disposed या _isDisposed फ़ील्ड को बेनकाब करें और इसे जांचें।


2

Disposeविधि जो भी सफाई एक वस्तु का त्याग कर दिया है से पहले की आवश्यकता होगी करने के लिए आवश्यक है; यदि कोई सफाई की आवश्यकता नहीं है, तो कुछ भी करने की आवश्यकता नहीं है। ऑब्जेक्ट को ट्रैक रखने के लिए आवश्यक है कि क्या यह निपटाया गया है, तब भी जब Disposeविधि अन्यथा कुछ भी नहीं करेगी, IDisposableबहुत सीमित लाभ के लिए कई वस्तुओं को ध्वज जोड़ने की आवश्यकता होगी ।

यदि IDisposableदो गुणों को शामिल किया गया है तो यह मददगार हो सकता है - एक जिसमें संकेत दिया गया है कि क्या किसी वस्तु को निपटाने की आवश्यकता है , और जिनमें से एक ने संकेत दिया कि वस्तु को निपटान द्वारा बेकार नहीं किया गया है । उन वस्तुओं के लिए जहां निपटान वास्तव में कुछ करता है, दोनों मूल्य शुरू में सच होंगे, और बाद में झूठे हो जाएंगे Dispose। उन वस्तुओं के लिए जहां निपटान के लिए कोई सफाई करने की आवश्यकता नहीं होती है, पहली विधि हमेशा झूठी हो सकती है और दूसरा हमेशा सच होता है, बिना किसी ध्वज को कहीं भी संग्रहीत किए बिना। मुझे नहीं लगता कि कोई भी तरीका है जो अभी .NET में जोड़ा जा सकता है, हालांकि।


IMHO, दो झंडे overkill है। मुझे लगता है कि सामान्य प्रतिमान के साथ रहना बेहतर है, जहां एक बार एक झंडे को एक वस्तु पर बुलाया जाता है। अन्यथा आप जटिलता जोड़ते हैं, केवल यह जानने के लिए कि कुछ वस्तुएं "अभी भी उपयोगी हैं" भले ही उन पर डिस्पोज को बुलाया गया हो। इसके लायक नहीं है कि सड़क नीचे जा रहा है।
टूलमेकरसेव

@ टूलमेकरसेव: आमतौर पर शून्य या एक झंडे होते हैं। निपटान की आवश्यकता वाली वस्तुओं के लिए, "निपटान की आवश्यकता है" और "उपयोगी है" गुणों को निपटाने के लिए "सही / सच्चा" मिलेगा और "झूठे / झूठे" बाद में, लेकिन उन वस्तुओं के लिए जहां निपटान कोई विकल्प नहीं होगा, दोनों बिना शर्त के होंगे "असत्य / सत्य" लौटाएँ। यह कहते हुए कि किसी वस्तु को अभी भी निपटाने की आवश्यकता है जब वह कभी ऐसा नहीं करता है, या वह वस्तु तब उपयोगी नहीं होती है जब वह हमेशा होती है, बल्कि icky होगी। मुझे लगता है कि एक अन्य प्रकार का उपयोग करने के लिए एक एन्यूमरेटेड प्रकार का उपयोग करना होगा, यह इंगित करने के लिए कि क्या एक प्रकार के निपटान की आवश्यकता है, निपटाया गया है, या बस परवाह नहीं करता है।
सुपरकैट

@ToolmakerSteve: मुझे लगता है कि बड़े कारण के IDisposableपास कोई Disposedसंपत्ति नहीं है, यह ऐसा माना जाता है कि ऐसी वस्तुएं होना अजीब है जहां कॉलिंग Disposeऐसी संपत्ति स्थापित नहीं करेगी true, लेकिन आवश्यकता होती है कि वस्तुएं Disposeउन मामलों पर नज़र रखती हैं जहां मामलों में बुलाया गया था वे अन्यथा कोई कारण नहीं होगा देखभाल करने के लिए महत्वपूर्ण लागत और थोड़ा लाभ जोड़ देगा।
सुपरकैट

1

मैं देख रहा हूं कि यह पुराना है, लेकिन मुझे इसका जवाब नहीं मिला। कुछ नहीं सभी DataSet की तरह डिस्पोजेबल वस्तुओं एक निपटाने की घटना है जो आप संलग्न कर सकते हैं।

class DisposeSample : IDisposable
{
    DataSet myDataSet = new DataSet();
    private bool _isDisposed;

    public DisposeSample()
    {
        // attach dispose event for myDataSet
        myDataSet.Disposed += MyDataSet_Disposed;
    }

    private void MyDataSet_Disposed(object sender, EventArgs e)
    {
        //Event triggers when myDataSet is disposed
        _isDisposed = true; // set private bool variable as true 
    }


    public void Dispose()
    {
        if (!_isDisposed) // only dispose if has not been disposed;
            myDataSet?.Dispose(); // only dispose if myDataSet is not null;
    }
}

जानकार अच्छा लगा। विशेष रूप से, Disposedघटना System.ComponentModel.IComponentइंटरफ़ेस का एक सदस्य है ।
टूलमेकरसेव

-1

मुझे क्या करना पसंद है, वस्तुओं को प्रारंभिक रूप से घोषित किए बिना घोषित करें, लेकिन उनके डिफ़ॉल्ट मानों को सेट करें Nothing। फिर, मैं जो लूप के अंत में लिखता हूं:

If anObject IsNot Nothing Then anObject.Dispose()

यहाँ एक पूरा नमूना है:

Public Sub Example()
    Dim inputPdf As PdfReader = Nothing, inputDoc As Document = Nothing, outputWriter As PdfWriter = Nothing

    'code goes here that may or may not end up using all three objects, 
    ' such as when I see that there aren't enough pages in the pdf once I open  
    ' the pdfreader and then abort by jumping to my cleanup routine using a goto ..

GoodExit:
    If inputPdf IsNot Nothing Then inputPdf.Dispose()
    If inputDoc IsNot Nothing Then inputDoc.Dispose()
    If outputWriter IsNot Nothing Then outputWriter.Dispose()
End Sub

यह आपकी मुख्य वस्तुओं को एक दिनचर्या के शीर्ष पर रखने के लिए, उन्हें एक Tryदिनचर्या के अंदर उपयोग करने और फिर उन्हें एक Finallyब्लॉक में निपटाने के लिए बहुत अच्छा काम करता है :

Private Sub Test()
    Dim aForm As System.Windows.Forms.Form = Nothing
    Try
        Dim sName As String = aForm.Name  'null ref should occur
    Catch ex As Exception
        'got null exception, no doubt
    Finally
        'proper disposal occurs, error or no error, initialized or not..
        If aForm IsNot Nothing Then aForm.Dispose()
    End Try
End Sub

6
@ LarsHöppner: प्रश्न का सार भाषा-अज्ञेय है, और अच्छा C # डेवलपर्स को उपरोक्त कोड को पढ़ने के लिए कम से कम पर्याप्त VB.NET पता होना चाहिए (और VB.NET डेवलपर्स को सी कोड को पढ़ने के लिए पर्याप्त C # सीखना चाहिए जो ऐसा नहीं करता है कुछ भी करो विशेष रूप से विदेशी)।
सुपरकैट

3
आप एक Usingबयान का उपयोग करने के बजाय यह सब क्यों करेंगे ? यह निश्चित रूप से 2013 में वापस मौजूद था जब यह उत्तर लिखा गया था।
कोड़ी ग्रे

वास्तव में "GoodExit:" यह एक गोटो के लिए 1983 क्या है ?? कृपया उसका उपयोग बंद करें।
मूसा

इस सवाल का जवाब नहीं है। विशेष रूप से, एक बार inputPdfएक मूल्य (कुछ भी नहीं के अलावा) पर सेट किया गया है, आपका जवाब यह जानने का कोई तरीका नहीं दिखाता है कि क्या inputPdfनिपटाया गया है। आप इसे निपटाने के बाद सेटिंग द्वारा आंशिक रूप से संबोधित कर सकते हैं inputPdf = Nothing। हालांकि यह किसी भी अन्य चर की मदद नहीं करेगा जो कि उसी वस्तु के रूप में इंगित किया गया है inputPdf। : यह यदि आप ऐसा है inputPdf = New PdfReader, Dim pdf2 As PdfReader = inputPdf, inputPdf.Dispose, inputPdf = Nothing, वहां अभी भी कोई रास्ता नहीं पता है कि हो सकता है pdf2निपटान किया जाता है (यह रूप में एक ही वस्तु है inputPdf)।
टूलमेकरसैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.