2011-08-30 12 views
7

की आवश्यकता होती है आप एक इंटरफेस IFooएक अंतरफलक जहां केवल कुछ कार्यान्वयन IDisposable

public interface IFoo 
{ 
    void Bar(); 
} 

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

संपादित

इसकी स्पष्ट रूप से बेहतर IFooIDisposable लागू किसी भी जिम्मेदारी ग्राहक से दूर ले करने के लिए। यह कैसे पता चलेगा कि कब और कब जांचना है कि कुछ संभवतः आईडीस्पोज़ेबल है या नहीं? उन्हें अन्यथा सब कुछ के साथ ऐसा करना होगा। हर कोई कुछ खाली निपटान() विधियों से सहमत होने लगता है किसी को भी चोट नहीं पहुंचाएगा।

इस सवाल से बाहर निकलने की सबसे अच्छी बात यह है कि मार्क ग्रेवेल के जवाब में "जैसा" और "उपयोग" के साथ कुछ डिस्पोजेबल हो सकता है या नहीं।

public interface IDisposableFoo : IFoo, IDisposable 
{ 
} 

किसी भी वर्ग इस इंटरफेस इनहेरिट अभी भी एक IFoo के रूप में इलाज किया जा सकता है:

+4

यदि कॉलर केवल 'IFoo' के बारे में जानता है, और 'IFoo' के कुछ कार्यान्वयन का निपटारा किया जाना चाहिए,' IFoo' को' IDISposable' का उत्तराधिकारी होना चाहिए। – Dyppl

+0

हाँ मैंने उल्लेख किया है कि मेरे प्रश्न में, कंक्रीट कक्षाओं में IDISposable के अनावश्यक कार्यान्वयन से बचने के लिए समस्या के किसी भी अन्य दृष्टिकोण के बारे में उत्सुक था, जिसकी आवश्यकता नहीं थी। –

+0

एकमात्र अन्य विकल्प कॉलर पक्ष पर 'आईडीस्पोजेबल' लागू करने वाले गीलेर को जांचने के लिए है, मेरा उत्तर देखें। – Dyppl

उत्तर

7

का उपयोग कर मुझे लगता है मैं बस की मांग करता हूँ IDisposable() - नो-सेशन Dispose() एक बड़ा भूमि के ऊपर नहीं है।

आप यकीन नहीं है कि यह डिस्पोजेबल है नहीं किया जा सकता है, तो निम्न सुंदर प्रभावी है:

var mightBeDisposable = GetBlah(); 
using(mightBeDisposable as IDisposable) 
{ 
    // etc 
} 
+0

क्योंकि अगर "as" विफल रहता है तो यह अपवाद फेंकने के बजाए शून्य हो जाता है और इसलिए हमेशा ब्लॉक का उपयोग कर सही होगा? –

+0

@ पीटर सही; और 'उपयोग' में पहले से ही (spec में) एक 'शून्य' चेक शामिल है, इसलिए केवल 'डिस्प्ले() 'को कॉल करने का प्रयास किया जा सकता है, जो' mayDeDisposable' 'IDisposable' (और इसलिए एक गैर-शून्य मान' मनाया गया था) –

+0

समझ गया, धारा 8.13 "अगर (संसाधन! = शून्य) (पहचान योग्य) संसाधन)।();" –

1

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

+0

इस इंटरफ़ेस के कार्यान्वयन जिन्हें IDISposable की आवश्यकता नहीं है, उसे अभी भी इसे लागू करने की आवश्यकता होगी। –

+0

@ पीटर केली - फिर उन कार्यान्वयन के लिए IFoo इंटरफ़ेस का उपयोग करें। यह विकल्प कोड में स्पष्ट रूप से दिखने का एक तरीका है कि एक डिस्पोजेबल विकल्प –

0

आपको या तो 2 इंटरफेस की आवश्यकता है जो IDISposable लागू करता है और एक ऐसा नहीं करता है - IFoo और IDisposableFoo या बस IFoo डिस्पोजेबल बनाएं।

IDisposable के कुछ खाली कार्यान्वयन में कोई हानि नहीं है। यह देखते हुए कि आपके पास पहले से ही कुछ हैं जिनके लिए निपटान की आवश्यकता है, ऐसा लगता है कि यह संभावित उपयोग केस है।

1

आप अपने फोन करने साइट के लिए कुछ कोड जोड़ने से परहेज नहीं करते हैं, तो आप सिर्फ निम्न कर सकते हैं:

IFoo foo = GetMeSomeFoo(); 

foo.UseFoo(); 

var disposableFoo = foo as IDisposable; 
if (disposableFoo != null) 
    disposableFoo.Dispose(); 

सुंदर नहीं है, लेकिन अपने इंटरफेस को दूषित नहीं करता। यह सुनिश्चित नहीं करता है कि कॉलर यह सब कुछ करेगा, या तो।

संपादित करें: के रूप में हंस Passant ने कहा, यह अनिवार्य रूप से

IFoo foo = GetMeSomeFoo(); 
using (foo as IDisposable) { 
    foo.UseFoo(); 
} 
+0

इस दृष्टिकोण के साथ समस्या यह है कि आप उपयोग करने वाले कीवर्ड का उपयोग नहीं कर रहे हैं –

+0

@ हंस पासेंट: साफ, मुझे नहीं पता था कि 'व्यवहार' का उपयोग करना इस तरह 'शून्य' मानों के साथ, धन्यवाद – Dyppl

1

के बराबर मैं IFoo IDisposable को लागू करने के रूप में यह ठोस के खिलाफ है मजबूर नहीं करेंगे। यदि आप चाहें तो आप IFoo से IDISposableFoo प्राप्त कर सकते हैं या यदि आप चाहें तो चेक (या यहां तक ​​कि कस्टम विधि जो IFoo को डिस्पोजेबल एडाप्टर में लपेटती है और IDISposable के लिए चेक) कर सकती है।

class DisposableAdapter : IDisposable, IFoo 
{ 
    IFoo _obj; 
    public DisposableAdapter(IFoo obj) 
    { 
     _obj = obj; 
    } 

    public void Dispose() 
    { 
     if (_obj is IDisposable) 
     ((IDisposable)obj).Dispose(); 
    }  

    // copy IFoos implementations from obj 

} 

using(var foo = new DisposableAdapter(myFoo)) //... use foo just as you had myFoo 
+2

आप किस सॉलिड दिशानिर्देश का तर्क देते हैं कि इसका उल्लंघन होता है? –

+0

मैं एसआरपी और आईएसपी के कुछ संयोजन के लिए बहस करता हूं - चाचा बॉब इसे "इंटरफेस प्रदूषण" कहते हैं। खाली तरीकों को लागू करने के लिए कुछ फूज़ को मजबूर क्यों करें? – Carsten

3

इंटरफेस कि IDisposable को लागू करने के लिए .NET फ्रेमवर्क में उदाहरण हैं - उदाहरण के IComponent, IDataReader के लिए।

यह एक उचित पैटर्न प्रतीत होता है जब आप अपेक्षा करते हैं कि अधिकांश कार्यान्वयन निपटान की आवश्यकता है।

+0

अच्छा बिंदु। उपयोगकर्ता अपेक्षाएं –

2

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

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

दूसरी तरफ, यदि किसी ऑब्जेक्ट का अंतिम उपयोगकर्ता इस तथ्य के अलावा कुछ भी नहीं जानता है कि यह कुछ इंटरफ़ेस लागू करता है, तो उस इंटरफेस को IDisposable (शायद विशेष रूप से!) का उत्तराधिकारी होना चाहिए यदि केवल एक छोटा सा अंश कार्यान्वयन के लिए सफाई की आवश्यकता होगी। IEnumerable बनाम IEnumerable<T> के मामले पर विचार करें। IEnumerable<T>.GetEnumerator() पर कॉल करने वाला कोई भी कोड ब्रह्मांड में कहीं भी एक ऑब्जेक्ट में एकमात्र संदर्भ होने की संभावना है जो IDisposable लागू करता है। इस प्रकार, यह कोड यह सुनिश्चित करने की ज़िम्मेदारी मानता है कि Dispose उस संदर्भ पर कॉल किया जाता है। कोई भी कोड जो IEnumerable<T>.GetEnumerator() पर कॉल करता है और न तो लौटाए गए मूल्य पर Dispose पर कॉल करता है और न ही ऐसा करने वाले अन्य कोड को देता है जो ऐसा करने का वादा करता है।

गैर-जेनेरिक IEnumerable.GetEnumerator द्वारा लौटाया गया प्रकार IDisposable लागू नहीं करता है। ऐसा लगता है कि ऐसा लगता है कि IEnumerable.GetEnumerator पर कॉल करने वाले कोड को निपटाने की ज़िम्मेदारी नहीं है। दुर्भाग्य से, इस तरह के निहितार्थ गलत है। कोड जो IEnumerable.GetEnumerator पर कॉल करता है, यह सुनिश्चित करने की ज़िम्मेदारी है कि यदि विशेष उदाहरण IDisposable लागू करता है, तो इसकी Dispose विधि को कॉल किया जाना चाहिए। संहिता जो उस जिम्मेदारी को कायम नहीं रखती है वह कोड से कम नहीं है जो IEnumerable<T>.GetEnumerator से वापसी का निपटान करने में विफल रहता है। वापसी प्रकार (यानी IEnumerator) की विफलता IDisposable लागू करने के लिए लौटाई गई वस्तु को साफ करने के लिए कॉलर की ज़िम्मेदारी को खत्म नहीं करती है। यह केवल ऐसी ज़िम्मेदारी को और अधिक बोझिल बनाता है, और यह संभावना बढ़ जाती है कि कोड ऐसा करने में विफल रहेगा।

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