क्या ऐसे संदर्भ में 'का उपयोग करना' उचित है जहां निपटान करने के लिए कुछ भी नहीं है?


9

C # में, usingबयान का उपयोग एक निर्धारित तरीके से निपटाने के लिए किया जाता है, बिना कचरा कलेक्टर की प्रतीक्षा किए। उदाहरण के लिए, इसका उपयोग किया जा सकता है:

  • SQL कमांड या कनेक्शन का निपटान करें,

  • बंद धाराओं, एक फ़ाइल की तरह अंतर्निहित स्रोत को मुक्त करना,

  • मुफ्त GDI + तत्व,

  • आदि।

मैंने देखा कि usingउन मामलों में अधिक से अधिक उपयोग किया जाता है जहां निपटान के लिए कुछ भी नहीं है, लेकिन जहां कॉल करने वाले के लिए usingदो अलग-अलग आदेशों के बजाय एक ब्लॉक लिखना अधिक सुविधाजनक है ।

उदाहरण:

  • मिनीप्रोफाइलर , स्टैक ओवरफ्लो टीम द्वारा लिखित, usingब्लॉक को प्रोफाइल को दर्शाने के लिए उपयोग करता है:

    using (profiler.Step("Name goes here"))
    {
        this.DoSomethingUseful(i - 1);
    }

    एक वैकल्पिक दृष्टिकोण में दो ब्लॉक होंगे:

    var p = profiler.Start("Name goes here");
    this.DoSomethingUseful(i - 1);
    profiler.Stop(p);

    कार्यों का उपयोग करने के लिए एक और तरीका होगा:

    profiler.Step("Name goes here", () => this.DoSomethingUseful(i - 1));
  • ASP.NET MVC ने usingफॉर्म भी लिए:

    <% using (Html.BeginForm())
       { %>
           <label for="firstName">Name:</label>
           <%= Html.TextBox("name")%>
           <input type="submit" value="Save" />    
    <% } %>

क्या ऐसा उपयोग उचित है? इसे कैसे उचित ठहराया जाए, यह देखते हुए कि कई कमियां हैं:

  • शुरुआती लोग खो जाएंगे, क्योंकि इस तरह का उपयोग उन लोगों के अनुरूप नहीं है जिन्हें पुस्तकों और भाषा विनिर्देश में समझाया गया है,

  • कोड अभिव्यंजक होना चाहिए। यहां, अभिव्यक्तता ग्रस्त है, क्योंकि उचित उपयोग usingयह दिखाने के लिए है कि पीछे, एक संसाधन है, जैसे एक धारा, एक नेटवर्क कनेक्शन या एक डेटाबेस जो कचरा कलेक्टर का इंतजार किए बिना जारी किया जाना चाहिए।


2
दो अलग-अलग कथन होने का दृष्टिकोण बिना समस्या के भोले संसाधन प्रबंधन के समान समस्या से ग्रस्त है using: बाद वाला बयान (जैसे profiler.Stop(p)) अपवादों और नियंत्रण प्रवाह के सामने निष्पादित होने की गारंटी नहीं है।

1
@ डायलेन: यह बताता है कि मिनीप्रोफाइलर ने दूसरे दृष्टिकोण से परहेज क्यों किया। लेकिन दूसरे मामले में सभी मामलों से बचा जाना चाहिए, क्योंकि इसे लिखना और बनाए रखना मुश्किल है।
आर्सेनी मूरज़ेंको



जवाबों:


7

आपका अंतिम कथन - कि "उपयोग करने का उपयुक्त उपयोग यह दिखाना है कि पीछे, एक संसाधन है, जैसे एक धारा, एक नेटवर्क कनेक्शन या एक डेटाबेस जो कचरा कलेक्टर के इंतजार किए बिना जारी किया जाना चाहिए" गलत है, और इसका कारण है डॉक्यूमेंटेशन के लिए आईडीसोपायरी इंटरफ़ेस: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

इस इंटरफ़ेस का प्राथमिक उपयोग अप्रबंधित संसाधनों को जारी करना है।

इसलिए, यदि आपकी कक्षा किसी भी अप्रबंधित रिज़ॉर्ट का उपयोग करती है, तो यह कोई फर्क नहीं पड़ता कि आप GC को क्या करना चाहते हैं या नहीं कर सकते हैं - यह GC के साथ कुछ भी नहीं करना है क्योंकि मानव रहित संसाधन GC'ed ( https: // stackoverflow) नहीं हैं। com / सवाल / 3607213 / क्या-का-द्वारा-मतलब-प्रबंधित-बनाम-अप्रबंधित-संसाधन-इन-नेट )।

तो "का उपयोग" के उद्देश्य के जीसी पर इंतजार कर से बचने के लिए नहीं है, यह उन अप्रबंधित संसाधनों का एक रिहाई के लिए मजबूर करने के लिए अब , इससे पहले कि वर्ग उदाहरण क्षेत्र से बाहर चला जाता है और यह अंतिम रूप कहा जाता है। यह उन कारणों के लिए महत्वपूर्ण है जो स्पष्ट होना चाहिए - एक अप्रबंधित संसाधन में अन्य अप्रबंधित संसाधनों पर निर्भरता हो सकती है, और यदि वे गलत क्रम में (या अंतिम रूप से) निपटाए जाते हैं तो खराब चीजें हो सकती हैं।

इसलिए यदि उपयोग किए जा रहे ब्लॉक में वर्ग को किसी भी मानव रहित संसाधन का उपयोग किया जाता है, तो उत्तर हां है - यह उचित है।

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

जो भी हो, "उपयोग" का अर्थ यह है कि वर्ग आईडीआईसपोजेबल को लागू करता है, इसलिए यह कोड की अभिव्यक्ति का उल्लंघन नहीं करता है; यह स्पष्ट करता है कि वास्तव में क्या चल रहा है।


"इस इंटरफ़ेस का प्राथमिक उपयोग अप्रबंधित संसाधनों को जारी करना है।" मैं कहता हूं कि Microsoft का प्रलेखन उस बिंदु पर बेकार है। हो सकता है कि वे एफसीएल में इसका उपयोग कैसे करते हैं, लेकिन एप्लिकेशन डेवलपर्स इसे अब एक दशक के करीब से विभिन्न चीजों के लिए उपयोग कर रहे हैं - कुछ अच्छे कारणों के लिए, कुछ नहीं-तो-अच्छे कारणों के लिए। लेकिन उनके डॉक के उस अंश के हवाले से ओपी के सवाल का जवाब बिल्कुल भी नहीं है।
जेसी सी। स्लीकर

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

1
आप मूल रूप से कह रहे हैं कि उद्देश्य GC के लिए प्रतीक्षा करने से बचना नहीं है, यह अंतिम रूप से प्रतीक्षा करने से बचें। लेकिन मुझे यह अंतर दिखाई नहीं दे रहा है: अंतिम रूप से GC कहा जाता है।
२२

जीसी एक गैर-नियतात्मक तरीके से संचालित होता है - आपको नहीं पता कि इसे कब बुलाया जाएगा। GC भी फ़ाइनलीज़र को ही कॉल करता है, लेकिन यह स्वयं को डिस्पोज़ नहीं करता है - वास्तविक संसाधन स्वयं GC के नियंत्रण से बाहर है। उपयोग करने के साथ (1) ऑब्जेक्ट को ठीक से स्कोप किया गया है, और (2) निपटान को ज्ञात बिंदु पर समय पर होने के लिए जाना जाता है - जब यह उपयोग ब्लॉक के दायरे से बाहर निकलता है, तो अप्रबंधित संसाधन चला गया है (या - सबसे खराब मामला - सौंप दिया गया कुछ और जो इसे नष्ट कर देगा)। वास्तव में, यह सिर्फ नाइटपैकिंग है; प्रलेखन पढ़ें, यह सब वहाँ दोहराया जाना चाहिए नहीं हैं।
मैक्सिमस मिनिमस

8

usingएक Dispose()विधि की उपस्थिति का तात्पर्य है । अन्य प्रोग्रामर मान लेंगे कि इस तरह की विधि ऑब्जेक्ट पर मौजूद है। नतीजतन, यदि कोई वस्तु डिस्पोजेबल नहीं है, तो आपको usingउस पर उपयोग नहीं करना चाहिए ।

कोड स्पष्टता राजा है। या तो ऑब्जेक्ट पर छोड़ें using, या लागू IDisposableकरें।

मिनीप्रोफाइलर usingएक प्रणाली के रूप में "बाड़" में कोड को प्रोफाइल किए जाने के लिए उपयोग करते हुए प्रतीत होता है । इसमें कुछ योग्यता है; मुमकिन है, मिनीप्रोफाइलर या तो Dispose()टाइमर को बंद करने के लिए बुला रहा है, या मिनीप्रोफाइलर ऑब्जेक्ट के दायरे से बाहर जाने पर टाइमर बंद हो जाता है।

अधिक आम तौर पर, आप तब आह्वान करेंगे usingजब किसी प्रकार के अंतिम रूप को स्वचालित रूप से होने की आवश्यकता होगी। दस्तावेज में html.BeginFormकहा गया है कि, जब विधि का उपयोग किसी usingकथन में किया जाता है , तो यह ब्लॉक </form>के अंत में समापन टैग को प्रस्तुत करता है using

जरूरी नहीं कि इसका मतलब यह है कि यह अभी भी दुरुपयोग नहीं है।


4
अब तक स्पष्ट है। सवाल यह है कि जब (अगर बिल्कुल भी) लागू करना उचित है IDisposable/ Dispose()इस दृष्टि से ओपी का वर्णन करने के लिए कुछ भी नहीं होने के बावजूद?

2
मुझे लगा कि मैंने स्पष्ट कर दिया है; ऐसा समय नहीं है जब यह उचित हो।
रॉबर्ट हार्वे

1
मेरी बात यह Disposeहै usingकि समझदारी सभी के लिए आवश्यक है (चाहे वह उपयुक्त हो)। ओपी के उदाहरण सभी लागू Disposeकरते हैं, क्या वे नहीं? और IIUC, प्रश्न यह है कि क्या यह सही है कि ये कक्षाएं Disposeकिसी अन्य विधि (जैसे Stop()कि मिनीप्रोफ़ाइलर) के बजाय उपयोग करती हैं।

1
हाँ, लेकिन यह सवाल नहीं है। सवाल यह है कि क्या ऐसा करना एक अच्छा विचार है।

2
@delnan: फिर से, मुझे लगा कि मैंने स्पष्ट कर दिया है। यदि यह आपके कोड के इरादे को स्पष्ट करता है, तो यह एक अच्छा विचार है। यदि ऐसा नहीं है, यह नहीं है।
रॉबर्ट हार्वे

1

usingत्रुटि और अपवाद सुरक्षित है। यह सुनिश्चित करता Dispose()है कि प्रोग्रामर द्वारा की जाने वाली किसी भी गलती के बावजूद इसे गलत कहा जाएगा। यह अपवादों को पकड़ने या संभालने में हस्तक्षेप नहीं करता है, लेकिन Dispose()जब अपवाद को फेंक दिया जाता है तो विधि को स्टैक के ऊपर पुनरावर्ती रूप से निष्पादित किया जाता है।

ऑब्जेक्ट जो कार्यान्वित करते हैं, IDisposeलेकिन जब वे किए जाते हैं तो निपटाने के लिए कुछ भी नहीं होता है। सबसे अच्छे हैं, भविष्य उनके डिजाइन का सबूत है। ताकि आपको अपने स्रोत कोड को फिर से तैयार न करना पड़े, जब भविष्य में उन्हें किसी चीज़ का निपटान करना पड़े।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.