2010-12-30 25 views
5
interface IMyInterace 
{ 
void Open(); 
object Read(); 
void Close(); 
} 

class MyImplementation : IMyInterface 
{ 
public void Open() { /* instantiates disposible class */ } 
//... 
public void Close() { /* calls .Dispose(); */ } 

} 

क्या इस प्रकार की स्थिति से निपटने का कोई अच्छा तरीका है यह सुनिश्चित करने के लिए कि कक्षा के अंदर डिस्पोजेबल उदाहरण कहें? (कॉलर्स को कोई संकेत नहीं है कि उन्हें दस्तावेज़ीकरण को छोड़कर 'बंद करें' को कॉल करना होगा।) IMyInterface के कार्यान्वयन आवश्यक रूप से IDISposible उदाहरणों को समाहित नहीं करते हैं और एप्लिकेशन के जीवन भर में बार-बार बंद हो जाते हैं और फिर से खोले जाते हैं।एक डिस्पोजेबल उदाहरण encapsulates की तुलना में एक वर्ग के साथ कैसे निपटने के लिए?

मैं ऐसा करने का सोच रहा हूँ:

  • MyImplementation में IDisposible को लागू करें।
  • सेट() को कॉल करने के लिए निपटान() सेट करें।
  • पिछला कॉल बंद होने के लिए ओपन की शुरुआत पर बंद() या निपटान() को कॉल जोड़ें।

IMyInterface के उपयोगकर्ताओं को वे क्या कार्यान्वयन का उपयोग कर रहे पता नहीं है, तो मुझे यकीन है कि कितना मूल्य MyImplementation disposible बन गया है, और फिर से, नहीं सब कार्यान्वयन IDisposibles संपुटित जाएगा नहीं कर रहा हूँ।

उत्तर

1

जवाब यहां पहले से ही करने के अलावा:

तो इस वर्ग (अक्सर/कभी कभी है

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

इससे आपके उपयोगकर्ता इन वस्तुओं का लगातार तरीके से उपयोग कर सकेंगे। दोष यह है कि आपको उन वर्गों को विधियों को निपटाने (डमी) को जोड़ने की आवश्यकता हो सकती है, जिन्हें वास्तव में इसकी आवश्यकता नहीं है। लेकिन लाभ स्थिरता और लचीलापन में है: क्या होगा अगर भविष्य में कक्षा बदलती है ताकि उसे निपटान() की आवश्यकता हो?

एक न्यूनतम दृष्टिकोण:

interface IMyInterace : IDisposable { } 

sealed class MyImplementation : IMyInterface 
{ 
    public void Open() { /* instantiates disposible class */ } 

    public void Close() { /* calls _myField.Dispose(); */ } 

    public void Dispose() { Close(); } // only use this short form in a sealed class 

} 
5

इसे संभालने का मानक तरीका केवल MyImplementationIDisposable लागू करना है।

3

जैसा कि जॉन ने उल्लेख किया है, आपका पहला बुलेट बिंदु सही है।

कभी-कभी Close() विधि Dispose() के साथ कार्यात्मक रूप से समानार्थी है, और एक अमूर्तता के साथ अर्थपूर्ण स्थिरता बनाए रखने के लिए मौजूद है। यही है, Open() विधि के पूरक के लिए। अन्य बार, Close() आपको फिर से खोलने की अनुमति देगा, लेकिन Dispose() नहीं होना चाहिए। आपका दूसरा बुलेट-पॉइंट इसलिए ठीक है।

बुलेट बिंदु 3 आवश्यक रूप से लागू नहीं है, क्योंकि एक डिस्पोजेड ऑब्जेक्ट का पुन: उपयोग नहीं किया जाना चाहिए। यदि आपको फिर से Open() पर कॉल करने की आवश्यकता है, तो आपको एक नया उदाहरण उपयोग करने की आवश्यकता है। वास्तव में, Open() विधि ObjectDisposedException को Dispose() पर एक बार फेंक दिया जाना चाहिए (एक निजी disposed बूलियन ध्वज की जांच करके)। यदि आप ऑब्जेक्ट को बंद करने के बाद पुन: खोलने का समर्थन करना चाहते हैं, तो आप Debug.Assert() और/या Open() को Close() के बिना बुलाए जाने पर अपवाद फेंकने पर विचार कर सकते हैं। यह इन उदाहरणों के मैला प्रबंधन को रोकने में मदद करेगा।

bool disposed; 

public void Dispose() // don't make virtual! 
{ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

protected virtual void Dispose(bool disposing) 
{ 
    if(!disposed) 
    { 
     if(disposing) 
     { 
      // dispose of managed resources here, for example: 
      // if(resource != null) { resource.Dispose(); } 
     } 
    } 

    // dispose of unmanaged resources here 

    disposed = true; 
} 
+2

पूर्ण डिस्पोजेबल पैटर्न जरूरत नहीं है।एक विनाशक के लिए कोई ज़रूरत नहीं है और इसलिए SuppressFinalize के लिए नहीं। –