2015-07-20 10 views
5

से विरासत में प्राप्त कक्षा में IDISposable इंटरफ़ेस को कैसे कार्यान्वित करें I C# .NET 4.0 में एक विशाल प्रोजेक्ट पर काम करता हूं। System.Net.Sockets.SocketAsyncEventArgs कक्षा से विरासत में प्राप्त एक कस्टम वर्ग है। निम्नलिखित की तरह कुछ:SocketAsyncEventArgs

public class SocketTaskArgs : SocketAsyncEventArgs 
{ 
    public SocketTaskArgs() 
    { 
     Completed += someEventhHandler; 
    } 

    public void CleanUp() 
    { 
     Completed -= someEventhHandler; 
    } 

    /* 
     There is a lot of code here that is unimportant at the moment. 
    */ 
} 

तो, मैं फेंक करने के लिए (bool) विधि क्लीनअप() विधि की सामग्री ले जाने के लिए चाहता था। SocketAsyncEventArgs (जाओ करने के लिए परिभाषा ताकि मैं स्रोत के रूप में मेटाडाटा देखा उपयोग करते हुए) -

के रूप में पहले, मैं आधार वर्ग के स्रोत कोड की जाँच की। मुझे पता चला, यह वर्ग IDISposable इंटरफ़ेस लागू करता है। अच्छा, मुझे बस निपटान (बूल) विधि को ओवरराइड करने की ज़रूरत है, है ना? (IDisposable Interface on MSDN देखें, अधिक जानकारी के लिए "पहचान योग्य और विरासत पदानुक्रम" अनुभाग। मेरे लिए कोई नई बात नहीं ... दुर्भाग्य से, SocketAsyncEventArgs वर्ग निम्नलिखित के रूप में कार्यान्वित किया जाता है:

public class SocketAsyncEventArgs : EventArgs, IDisposable 
{ 
    public void Dispose(); 

    //some other stuff here 
} 

इसका मतलब है, कोई रास्ता नहीं कैसे ओवरराइड करने के लिए है निपटान (bool) विधि, के रूप में यह रूप में निजी बजाय लागू हो जाता है संरक्षित ... इसका कारण क्या है?

अगला, मैंने एमएसडीएन पर SocketAsyncEventArgs.Dispose() विधि पढ़ी।

नोट्स उत्तराधिकारियों को

निपटान अन्य वस्तुओं से कई बार कहा जा सकता है: अजीब बात यह है कि, यह निम्न अनुभाग होता है। ओवरराइड करते समय (बूलियन), सावधान रहें ऑब्जेक्ट्स को संदर्भित न करें जिन्हें पहले पर पहले कॉल में निपटाया गया था का निपटान करें। को कार्यान्वित करने के तरीके के बारे में अधिक जानकारी के लिए (बूलियन), एक निपटान विधि को कार्यान्वित करना देखें।

रुको ... क्या?

जब निपटान (बूलियन), अधिभावी ...

मैं कैसे निपटान (बूलियन) ओवरराइड करना चाहिए?

इस मामले में आईडीस्पोजेबल इंटरफेस को लागू करने के लिए अनुशंसित तरीका क्या है?

+1

यह निजी नहीं है, यह बिल्कुल लागू नहीं हुआ है (http://referencesource.microsoft.com/System/net/System/Net/Sockets/Socket.cs.html#8877 देखें)। यह एक फाइनलाइज़र का उपयोग करता है लेकिन ऐसा लगता है कि इसे वास्तव में अनुशंसित पैटर्न में लागू नहीं किया गया था। –

+0

ऐसा लगता है कि 'निपटान' सार्वजनिक है, सिर्फ 'आभासी' नहीं। –

+0

आपको उस कक्षा से उत्तराधिकारी नहीं होना चाहिए। आप शायद एक बड़ी मौजूदा परियोजना में आसानी से इसे बदल नहीं सकते हैं। – usr

उत्तर

3

वहाँ कुछ भी अपने बच्चे वर्ग पर IDisposable लागू करने से आप को रोकने के लिए किया प्रतीत नहीं होता है, इस उदाहरण लेते हैं:

public class DisposableParent : IDisposable 
{ 
    public void Dispose() 
    { 
     Console.WriteLine("The parent was disposed."); 
    } 
} 

public class DisposableChild : DisposableParent, IDisposable 
{ 
    public new void Dispose() 
    { 
     base.Dispose(); 
     Console.WriteLine("The child was disposed."); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     using (DisposableChild c = new DisposableChild()) { } 
     Console.ReadKey(true); 
    } 
} 

निम्नलिखित उत्पादन देता है:

माता पिता निपटारा किया गया था।

बच्चे का निपटारा किया गया था।

संकलक बच्चे में माता पिता के वर्ग के निपटाने छुपा है, तो new ऑपरेटर का उपयोग उस चेतावनी से छुटकारा मिलता है के बारे में चेतावनी देते हैं, सिर्फ बच्चे कक्षा से आधार वर्ग Dispose कॉल करने के लिए सुनिश्चित कर लें (और इसे लागू सही रास्ता)।

बच्चे की तरह कुछ हो जाएगा के लिए निपटाने:

public class DisposableChild : DisposableParent, IDisposable 
{ 
    private bool _disposed = false; 

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

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (!_disposed) 
      { 
       base.Dispose(); 
       Console.WriteLine("The child was disposed."); 
       _disposed = true; 
      } 
     } 
    } 
} 

और हाँ, यह अभी भी काम करता है अगर आप की तरह कुछ कार्य करें:

using (DisposableParent p = new DisposableChild()) 
{ 

} 

लेकिन कुछ इस तरह इसे तोड़ सकते हैं:

public class Program 
{ 
    public static void Main() 
    { 
     DisposableChild c = new DisposableChild(); 
     DisposeOfIt(c); 

     Console.ReadKey(true); 
    } 

    public static void DisposeOfIt(DisposableParent p) 
    { 
     p.Dispose(); 
    } 
} 

केवल प्रिंट करता है कि माता-पिता का निपटारा किया गया था। तो यदि आपने इस विधि का उपयोग किया है तो आपको अपनी वस्तुओं के जीवनकाल को नियंत्रित करने के बारे में सावधान रहना होगा।

+0

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

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