6

आप 3 वर्गों कि IDisposable लागू है कहो - ए, बी और सी वर्ग ए और बी दोनों वर्ग सी पर निर्भर हैंIDISposable पैटर्न का एक समस्याग्रस्त उदाहरण?

  1. यह कहना सही नहीं होगा कि कक्षाएं एक और निपटान के बी के विशिष्ट कार्यान्वयन() होगा:

    public void Dispose() 
    { 
        if (m_C != null) m_C.Dispose(); 
    } 
    
  2. अगर वहाँ है कि साझा सी का एक ही उदाहरण एक का एक उदाहरण और और बी के कहने है, तुम कैसे समस्या यह है कि एक का एक उदाहरण निपटाने को नुकसान होगा पर काबू पाने के हैं वें ई का उदाहरण बी?

  3. अंतिम मिनट परिशिष्ट - यदि बिंदु 2 में यह एक डी कंटेनर है जो सभी उदाहरणों को तत्काल करता है, जो वस्तुओं का निपटान करने के लिए जिम्मेदार हैं? क्या यह कंटेनर स्वयं है? कैसे?

धन्यवाद, urig

उत्तर

12

निपटाने पैटर्न वहाँ एक अच्छी तरह से स्थापित "मालिक" जो जब संसाधन का निपटारा किया जाना चाहिए तय करने के लिए हो जाता है किया जा रहा है पर निर्भर करता है।

यदि ए और बी को सी के समान उदाहरण को संदर्भित करने की आवश्यकता है, तो उनमें से केवल एक को "स्वामी" के रूप में कार्य करना चाहिए।

जबकि आप कर सकते हैं संदर्भ गणना के लिए क्या मात्रा है, मुझे आमतौर पर यह पता लगाना बेहतर होता है कि "मालिक" क्या है। उदाहरण के लिए, जब आप Bitmap स्ट्रीम के साथ Bitmap बनाते हैं, तो Bitmap पर उस बिंदु से स्ट्रीम का मालिक होता है, और आपको इसे स्वयं का निपटान नहीं करना चाहिए। यह कुछ मुद्दों का कारण बन सकता है, लेकिन यह संदर्भ गिनती को खत्म करने की कोशिश करने से अंततः सरल है।

+0

जॉन का 1 9 5 प्रतिनिधि है :) –

+0

मेरे परिदृश्य में ए और न ही बी के विशिष्ट मालिक हैं। उदाहरण के लिए कल्पना करें कि सी वास्तविक समय में डेटा को धक्का देता है और ए और बी दोनों इसका उपभोग करते हैं। एक डी कंटेनर ए और बी के लिए तत्काल सी के प्रभारी है, लेकिन इसका निपटान करने का प्रभारी कौन है? – urig

+1

@urig: उस स्थिति में, आप * कब * इसे निपटाना चाहते हैं? मुझे आमतौर पर पता चलता है कि इस बारे में डिजाइन करने के तरीके हैं जो पूरी तरह से समस्या से बचते हैं, लेकिन यह स्थिति पर निर्भर करता है। –

4

एक अशक्त चेक के रूप में करता है, तो बी सी इस के disposes एक के संदर्भ अपडेट नहीं करेंगे मदद नहीं हो जाएंगे।

आपको यह सुनिश्चित करना होगा कि कक्षाओं में से केवल एक का सी का स्वामित्व है। यह मालिक वर्ग इसके निपटारे के लिए ज़िम्मेदार है।

आम तौर पर कक्षा जो सी बनाता है वह वर्ग होना चाहिए जो इसका निपटान करता है।

0

दो तरीकों मुझे लगता है कि हो सकता है किया जाएगा करने के लिए:

  1. सी के अन्दर एक माता पिता संग्रह बनाएँ, और ए और बी के निपटाने विधि में, बच्चे के माता पिता संग्रह से स्वयं को हटा दें। फिर यदि अभिभावक संग्रह गणना 0 है, तो निपटान करें।
  2. आलसी ए और बी दोनों के भीतर एक संपत्ति को लोड करने के लिए सी। सी पर एक शून्य जांच करें, अगर किसी अन्य वस्तु ने इसे नष्ट कर दिया है, तो इसे पुन: स्थापित करें (यदि संभव हो)।
0
  1. मैं आमतौर पर इसे इस तरह से करता हूं, इसे स्वीकार किया जाता है और यह निश्चित रूप से काम करता है। हालांकि अगर किसी अन्य वस्तु ने इसका निपटारा किया है, तो शून्य जांच फिर से बुलाए जाने का निपटान नहीं करेगी क्योंकि यह शून्य नहीं होगी। हालांकि, सी के निपटान को कई कॉलों के खिलाफ बचाव करना चाहिए।

  2. बहुत अच्छा सवाल है।तत्काल क्या स्प्रिंग्स को ध्यान में रखना है कि यह जानने के लिए तर्क होना चाहिए कि वर्तमान में उस वस्तु पर कितनी गिनती है, इसलिए यह स्वयं का निपटान दिनचर्या स्वयं की रक्षा कर सकता है। Semaphores यह करते हैं, लेकिन भारी हैं।

मैं यह भी पूछूंगा कि आप इसे वास्तविक दुनिया के उदाहरण में कहां देखेंगे, यह एक डिज़ाइन विसंगति हो सकती है। अपडेट: जैसा कि अन्य ने उल्लेख किया है, यह एक डिज़ाइन समस्या पर आ रहा है - सीसीडब्ल्यू का उपयोग करते समय आपको एक समान प्रभाव मिलता है, कोई अन्य अंतर्निहित COM ऑब्जेक्ट जारी करता है जहां अन्य उपयोगकर्ता अभी भी इसका उपयोग कर सकते हैं।

0

एक सही कार्यान्वयन होगा कि: हालांकि, आप A और B दोनों में C का एक विशिष्ट उदाहरण के आधार पर सभी वस्तुओं के लिए संदर्भ बचाने के लिए, और (वर्तमान के अलावा उस सूची के लिए खाली होने के लिए एक जांच करने के लिए चाहते हो सकता है निपटान वस्तु) C की Dispose विधि में।

1

केवल एक उदाहरण मालिक होना चाहिए, और यह निपटान के लिए ज़िम्मेदार है। गैर-मालिक उदाहरण को अटैच जैसे फ़ंक्शन का उपयोग करके सी संदर्भ प्राप्त करना चाहिए, और इसे इसे निपटाना नहीं चाहिए।

1

कौन उदाहरण उदाहरण बनाया? यह आम तौर पर मालिक है और उदाहरण का निपटान करने के लिए जिम्मेदार होना चाहिए।

संभावना है कि आपके पास एक "बाहरी" वर्ग है जिसने सी बनाया है और फिर इसे सीधे और अप्रत्यक्ष रूप से ए और बी में पारित किया है। यह शायद प्राकृतिक उम्मीदवार है जिसके पास सी के जीवन चक्र की ज़िम्मेदारी है, और इसका निपटान करना चाहिए यह।

[संपादित करें: ओपी की टिप्पणी के जवाब में] ऐसा लगता है कि आपको यहां डिज़ाइन पर एक और नज़र रखना चाहिए। क्या यह एक रिफैक्टर की आवश्यकता है?

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

मुझे लगता है कि मैं बस इतना कह रहा हूं कि ऐसा लगता है कि ऐसा लगता है कि यह एक ऐसे डिज़ाइन को इंगित कर सकता है जिसके लिए कुछ बदलाव की आवश्यकता है; एक गंभीर आंख के साथ एक और देखो।

+0

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

+0

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

1

अंतिम मिनट परिशिष्ट - बिंदु में अगर 2 यह एक डि कंटेनर कि सभी उदाहरणों को दर्शाता है, जो वस्तुओं के निपटान के लिए कौन जिम्मेदार है? क्या यह कंटेनर स्वयं है? कैसे?

हां, कंटेनर के पास IDisposable ऑब्जेक्ट्स हैं जो इसे बनाता है। जब कंटेनर स्वयं का निपटारा होता है तो कंटेनर इन वस्तुओं को निपटाता है। सभी डी कंटेनरों को डिफ़ॉल्ट रूप से यह पहले से ही करना चाहिए।

कभी-कभी डी ढांचा आपको स्वामित्व लेने का एक तरीका देता है। उदाहरण के लिए, ऑटोफैक में आप इंजेक्शन के लिए Owned<T> मांग सकते हैं, और फिर आप ऑब्जेक्ट के साथ किए जाने पर Owned<T>.Dispose() को सुरक्षित रूप से कॉल कर सकते हैं। यह विशेष रूप से उपयोगी होता है यदि आप गतिशील रूप से इंजेक्शन Func<Owned<T>> फैक्ट्री के माध्यम से उदाहरण बना रहे हैं। ध्यान दें कि ऐसे "स्वामित्व वाले उदाहरण" साझा किए जाने का इरादा नहीं है।

0

जोन ने कहा - इसके अलावा निर्माता मालिक है और डिस्पोजेबल का निपटान करना चाहिए।

इस मामले में यह कंटेनर है, और कंटेनर घटकों को निपटाने के लिए ज़िम्मेदार है। प्रत्येक घटक इसका समर्थन नहीं करता है (या कम से कम हर कोई नहीं)। Castle Windsor does। इसके अलावा ऑटोफैक इसका समर्थन करता है।

0

प्रत्येक IDisposable ऑब्जेक्ट में एक मालिक होना चाहिए। यदि किसी संसाधन को एकाधिक उपयोगकर्ताओं के बीच साझा करने की आवश्यकता होगी, जिनमें से कोई भी इसका उपयोग करने वाला अंतिम हो सकता है, तो प्रत्येक उपयोगकर्ता को अपने स्वयं के रैपर का संदर्भ रखना चाहिए। रैपर ऑब्जेक्ट्स को IDisposable के अलावा किसी अन्य निजी रूप से निर्मित आंतरिक-रैपर ऑब्जेक्ट के समन्वय के लिए कुछ साधनों का उपयोग करना चाहिए जो संसाधन पर Dispose पर कॉल करेंगे। आंतरिक रैपर ऑब्जेक्ट को क्लीनअप के लिए IDisposable का उपयोग करने की आवश्यकता नहीं है क्योंकि इसे सार्वजनिक रूप से उजागर नहीं किया गया है, और तथ्य यह है कि इसे IDisposable का उपयोग करने की आवश्यकता नहीं है, इसका अर्थ यह है कि यह कई मालिकों को समायोजित करने वाले क्लीनअप के माध्यमों का उपयोग कर सकता है।