मुझे लगता है कि करने के लिए है कि एक इंटरफेस पर IDisposable
डाल कुछ समस्याएं पैदा कर सकता शुरू कर रहा हूँ। इसका तात्पर्य है कि उस इंटरफ़ेस को लागू करने वाली सभी वस्तुओं का जीवनकाल सुरक्षित रूप से सिंक्रनाइज़ रूप से समाप्त हो सकता है। यानी, वह किसी को भी इस तरह कोड लिखने की अनुमति देता है और IDisposable
समर्थन करने के लिए सभी कार्यान्वयन की आवश्यकता है:
using (ISample myInstance = GetISampleInstance())
{
myInstance.DoSomething();
}
केवल कोड है जो ठोस प्रकार तक पहुँच रहा है वस्तु के जीवनकाल को नियंत्रित करने के सही तरीके से पता कर सकते हैं।उदाहरण के लिए, किसी प्रकार को पहले स्थान पर निपटान की आवश्यकता नहीं हो सकती है, यह IDisposable
का समर्थन कर सकता है, या इसे उपयोग करने के बाद awaiting
कुछ एसिंक्रोनस क्लीनअप प्रक्रिया की आवश्यकता हो सकती है (उदा।, something like option 2 here)।
एक इंटरफ़ेस लेखक कक्षाओं को लागू करने के सभी संभावित भविष्य के जीवनकाल/स्कोप प्रबंधन आवश्यकताओं की भविष्यवाणी नहीं कर सकता है। किसी इंटरफ़ेस का उद्देश्य किसी ऑब्जेक्ट को कुछ API को बेनकाब करने की अनुमति देना है ताकि इसे कुछ उपभोक्ता के लिए उपयोगी बनाया जा सके। कुछ इंटरफेस जीवनकाल प्रबंधन से संबंधित हो सकते हैं (जैसे कि IDisposable
स्वयं), लेकिन उन्हें जीवन भर प्रबंधन से संबंधित इंटरफेस के साथ मिलाकर इंटरफ़ेस को हार्ड या असंभव के कार्यान्वयन को लिखना हो सकता है। यदि आपके इंटरफ़ेस के बहुत कम कार्यान्वयन हैं और आपका कोड तैयार करते हैं ताकि इंटरफ़ेस का उपभोक्ता और जीवनकाल/स्कोप-मैनेजर एक ही विधि में हो, तो यह भेद पहले स्पष्ट नहीं है। लेकिन अगर आप अपने ऑब्जेक्ट को पास करना शुरू करते हैं, तो यह स्पष्ट होगा।
void ConsumeSample(ISample sample)
{
// INCORRECT CODE!
// It is a developer mistake to write “using” in consumer code.
// “using” should only be used by the code that is managing the lifetime.
using (sample)
{
sample.DoSomething();
}
// CORRECT CODE
sample.DoSomething();
}
async Task ManageObjectLifetimesAsync()
{
SampleB sampleB = new SampleB();
using (SampleA sampleA = new SampleA())
{
DoSomething(sampleA);
DoSomething(sampleB);
DoSomething(sampleA);
}
DoSomething(sampleB);
// In the future you may have an implementation of ISample
// which requires a completely different type of lifetime
// management than IDisposable:
SampleC = new SampleC();
DoSomething(sampleC);
sampleC.Complete();
await sampleC.Completion;
}
class SampleC : ISample
{
public void Complete();
public Task Completion { get; }
}
उपरोक्त कोड नमूने में, मैंने आपके द्वारा प्रदान किए गए दो में जोड़े गए तीन प्रकार के आजीवन प्रबंधन परिदृश्यों का प्रदर्शन किया।
SampleA
तुल्यकालिक using() {}
समर्थन के साथ IDisposable
है।
SampleB
शुद्ध कचरा संग्रह का उपयोग करता है (यह किसी भी संसाधन का उपभोग नहीं करता है)।
SampleC
उन संसाधनों का उपयोग करता है जो इसे सिंक्रनाइज़ तरीके से निपटाए जाने से रोकते हैं और इसके जीवनकाल के अंत में await
की आवश्यकता होती है (ताकि यह जीवन भर प्रबंधन प्रबंधन कोड को सूचित कर सके कि यह संसाधनों का उपभोग कर रहा है और किसी भी असीमित रूप से सामने आए अपवादों को बुलबुला करता है)।
रखने जीवन प्रबंधन द्वारा अपने अन्य इंटरफेस से अलग है, तो आप (Dispose()
लिए उदाहरण के लिए, आकस्मिक कॉल) डेवलपर गलतियों को रोकने के लिए और अधिक सफाई से भविष्य अप्रत्याशित जीवन/गुंजाइश प्रबंधन पैटर्न का समर्थन कर सकते हैं।
इंटरफ़ेस के खिलाफ लिखे गए कोड (संभावित रूप से पहले से निर्मित किए गए उदाहरण को सौंपने) कितनी संभावना है कि उस उदाहरण के * अंतिम * उपयोगी जीवनकाल के लिए ज़िम्मेदार है? –
@Damien_The_Unbeliever: ठीक है, मानते हैं कि ISample कारखाने विधि के परिणाम या निर्भरता इंजेक्शन के माध्यम से आता है। – Beachwalker
यह बात है - अगर यह * कारखाने से आ रही है, तो संभवतः आपका कोड * निपटान के लिए ज़िम्मेदार है - इसलिए मैं इसे इंटरफ़ेस पर रखूंगा। लेकिन अगर इसे इंजेक्शन दिया जा रहा है तो मुझे लगता है कि इंजेक्टर जीवन भर के लिए ज़िम्मेदार भी है, इसलिए यह * इंटरफेस पर फिट नहीं होगा - मुझे नहीं लगता कि एक आकार का फिट है-सवाल का सभी जवाब। –