2009-04-03 6 views
7

मैं कुछ हद तक नया हूं, जो स्क्रिप्टिंग भाषाओं के प्रति आदी है। मुझे 'उपयोग' का विचार पसंद है, आप किसी ऑब्जेक्ट को तुरंत चालू करते हैं, और फिर जब तक आपको इसकी आवश्यकता होती है तब तक आप अपने दायरे में काम करते हैं, फिर जब आप इसका उद्देश्य पूरा करते हैं तो आप इसे स्वयं का निपटान करते हैं।मैं 'उपयोग' का उपयोग करने के लिए सबसे अच्छी जगह कैसे जानूं?

लेकिन, यह मेरे लिए स्वाभाविक नहीं है। जब लोग मुझे इसका उपयोग करते हुए उदाहरण दिखाते हैं, तो मैं इसे नौकरी के लिए एक अच्छा उपकरण मानता हूं, लेकिन यह मेरे स्वयं के प्रोग्रामिंग में समस्याओं को हल करने के लिए कभी नहीं होता है।

using का उपयोग करने के लिए मैं अच्छी जगहों को कैसे पहचान सकता हूं और मैं इसे कोशिश-पकड़ ब्लॉक के साथ कैसे उपयोग कर सकता हूं। क्या वे ब्लॉक के अंदर जाते हैं, या आप आमतौर पर एक कोशिश ब्लॉक के भीतर एक उपयोग कथन संलग्न करना चाहते हैं?

उत्तर

9

मैं शायद ही कभी लिखने की कोशिश/पकड़ ब्लॉक - सबसे अपवाद (पास) ढेर के ऊपर तक फेंक दिया मिलता है। यदि मैं को एक कोशिश/पकड़ ब्लॉक की आवश्यकता है, तो मुझे यकीन नहीं है कि मैं इसे using कथन बनाम बाहर अंदर रखने के बीच विशेष रूप से संगत हूं। यह वास्तव में इस बात पर निर्भर करता है कि क्या आप अपवाद हैंडलिंग कोड चलाने के बाद संसाधन को निपटान करना चाहते हैं या नहीं।

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

+0

उन वस्तुओं को स्पष्ट करने के लिए जो आईडीआईस्पोजेबल को सीधे या विरासत के माध्यम से कार्यान्वित करते हैं (क्योंकि डैनिएल्टाल्स्की "कुछ हद तक सी #" है)। –

+0

धन्यवाद जोनाथन - उचित रूप से संपादित किया गया। –

+0

ठीक है, "कुछ हद तक नया सी #" मेरा मतलब है, "8 महीने से कम समय के लिए सी # में व्यावसायिक कोड लिख रहे हैं"। उदाहरण के लिए, मैं "उपयोग करने योग्य" से "उपयोग करने" के कनेक्शन से पहले ही परिचित था, जिसे मैं इस प्रश्न में उल्लेख करता हूं। यह "आजीवन नियंत्रण" भाग था जिसे मैं याद कर रहा था। – danieltalsky

18

using केवल IDisposable लागू करने वाले प्रकारों के साथ उपयोग किया जा सकता है; यह गारंटी देता है कि Dispose() विधि को तब भी बुलाया जाएगा जब कोई त्रुटि उत्पन्न होती है।

इस कोड:

using (MyDisposableType x = new MyDisposableType()) 
{ 
    // use x 
} 

इस के बराबर है:

MyDisposableType x = new MyDisposableType(); 
try 
{ 
    // use x 
} 
finally 
{ 
    x.Dispose(); 
} 
+0

तो ... किसी भी ऑब्जेक्ट पर इसका उपयोग करें जो IDISposable लागू करता है? हमेशा? – danieltalsky

+0

और अपवाद हैंडलिंग के बारे में क्या? – danieltalsky

+0

डाउनवॉटर कृपया एक टिप्पणी छोड़ दें। धन्यवाद। –

1

क्या मिच ने कहा, के साथ साथ ..

आप कथन का उपयोग बाहर या एक try..catch ब्लॉक यह वास्तव में आप क्या यानी कि क्या आप यथोचित एक फेंक करने के लिए कुछ उम्मीद प्राप्त करने के लिए कोशिश कर रहे हैं पर निर्भर करेगा अंदर उपयोग कर सकते हैं उदाहरण के लिए, एक विशेष वस्तु का उपयोग करते हुए अपवाद जिसे आप पुनर्प्राप्त करने की योजना बनाते हैं।

उसी टोकन से, आप एक ऑब्जेक्ट का निपटान भी कर सकते हैं जो अंततः ब्लॉक में IDISposable लागू करता है यदि आपको आवश्यकता हो।

3

मैं इस बारे में सोचने के लिए उपयोग करता हूं कि "हर बार इसका उपयोग करें जब आईडी लागू करने योग्य हो और आप इस विशेष उदाहरण की आवश्यकता के लिए नहीं जा रहे हैं"।

1

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

System.IO.FileStream writeStream = new System.IO.FileStream(fileName, System.IO.FileMode.OpenOrCreate)); 
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(writeStream)); 
//do smth 

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

using(System.IO.FileStream writeStream = new System.IO.FileStream(fileName, System.IO.FileMode.OpenOrCreate)) { 
    using(System.IO.BinaryWriter writer = new System.IO.BinaryWriter(writeStream)) { 
     //do stmth 
    } 
} 
+0

नहीं, ऑब्जेक्ट * अंतिम नहीं है। यह केवल निपटान है। अंतिमकरण और निपटान बहुत अलग हैं। आम तौर पर निपटान एक फाइनलाइज़र को दबाएगा (अगर कोई है) लेकिन वे एक ही बात नहीं हैं। –

+0

"जब आप निर्धारक वस्तु निपटान की आवश्यकता होती है तो इसका उपयोग करें।" ऐसा लगता है कि यदि कोई ऑब्जेक्ट IDISposable लागू करता है तो आपको ऑब्जेक्ट की आवश्यकता नहीं होने पर हमेशा इसे निपटाना चाहिए। आईडीस्पोजेबल को लागू करने से ऑब्जेक्ट कहता है "मैं (शायद) उन संसाधनों का उपयोग कर सकता हूं जिन्हें निपटान करने की आवश्यकता है"। –

+0

क्या होगा यदि प्रश्न में वस्तु का कार्यान्वयन एक बार में बदलता है और निपटान महत्वपूर्ण हो जाता है? उपयोग के बाद सही निपटान का लाभ क्या है? –

1

आप एक कोशिश/पकड़ ब्लॉक के अंदर एक उपयोग संलग्न कर सकते हैं और आप एक प्रयोग के अंदर एक कोशिश/पकड़ ब्लॉक संलग्न कर सकते हैं।

using (SqlConnection conn = new SqlConnection(connectionString)) 
using (SqlCommand command = new SqlCommand(sql, conn)) 
{ 
    // do something here 
} 

अब जब आप ब्लॉकों का उपयोग कर अपने आदेश निपटान किया जाता है छोड़ने के लिए और कनेक्शन बंद कर दिया जाता है:

एक स्थिति है जहाँ का उपयोग कर अच्छा है जब आप DBConnection का उपयोग कर डेटाबेस कार्यों और DBCommands कर रहे हैं।

1

क्या मिच ने कहा सही है। तो इसका उपयोग करने का मुख्य उपयोग यह सुनिश्चित करना है कि IDISposable ऑब्जेक्ट्स के बिना किसी प्रयास/पकड़ने या प्रयास/अंत में कथन कोड करने के लिए निपटा जाए।

अब, एक और अधिक उन्नत उपयोग है जो आपको दिलचस्प भी मिल सकता है। जब आप एक उपयोग कथन का उपयोग करते हैं, तो संकलक एक कोशिश/आखिरकार उत्पन्न करता है, और यह आपके द्वारा उत्पन्न होने वाले अंत में आपके लिए निपटान() को कॉल भी उत्पन्न करता है। आप इस निपटान() विधि को "हुक" के रूप में उपयोग करने के लिए कुछ भी करने के लिए उपयोग कर सकते हैं ... संसाधनों को जारी करने से संबंधित नहीं होना चाहिए।

उदाहरण के लिए, जेफरी रिचटर ने लिखा एक टाइमर ऑब्जेक्ट में इसका उपयोग करता है। आप इसके साथ कुछ इस तरह (वैचारिक केवल) कर सकते हैं:

using(var x = new Timer()) 
{ 
    // Do the operation you want timed 
} 

// Now, the timer has been stopped, because the 
// compiler-generated call to Dispose() has already 
// occurred, and Jeffrey uses Dispose() to stop 
// the timer. 
+0

थोड़ा मुश्किल लगता है। समापन ब्रेस के बाद आपके पास एक्स तक पहुंच नहीं है। फिर आप रुकने वाले टाइमर का लाभ कैसे उठा सकते हैं? –

+0

हाँ, यह सच है। रिक्टर के टाइमर के मामले में, वह कंसोल में विलुप्त समय (और कचरे के संग्रह की संख्या) का उत्पादन करता है। तो बंद होने के बाद वस्तु को संदर्भित करने की उसकी कोई अन्य आवश्यकता नहीं थी। –

+0

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

2

आप को पता है कि कैसे रचनात्मक, अपने खुद के डिजाइन के भीतर इसका इस्तेमाल परिस्थितियों के लिए अपने स्वयं के कोड के कुछ के माध्यम से देखना चाहते हैं जहां कोड की एक विशेष बिट संलग्न ब्लॉक से बाहर निकलने से पहले बिल्कुल निष्पादित होना चाहिए। ये ऐसी स्थितियां हैं जहां try/finally या using आपकी मदद कर सकते हैं।

विशेष रूप से, यदि आपने सभी अपवादों को पकड़कर इसे प्राप्त करने का प्रयास किया है, तो आपको वास्तव में try/finally या using पर बदलना होगा।

यदि पैटर्न कई बार होता है, तो आप पैटर्न को कैप्चर करने के लिए IDisposable लागू करने वाली कक्षा बना सकते हैं, और आपको using कथन के साथ पैटर्न का आह्वान करने की अनुमति देता है। लेकिन अगर आपके पास एक विशिष्ट मामला है जो एक-ऑफ लगता है, तो बस try/finally का उपयोग करें।

दो वास्तव में बहुत समान हैं, - usingtry/finally के मामले में निर्दिष्ट किया जाता है, लेकिन फिर भी अगर हम केवल using था, हम try/finally खुद बना सकते हैं:

public class DisposeAnything : IDisposable 
{ 
    public Action Disposer; 

    public void Dispose() 
    { 
     Disposer(); 
    } 
} 

अब आप कह सकते हैं:

using (new DisposeAnything 
     { 
      Disposer =() => File.Delete(tempFileName) 
     }) 
{ 
    // blah 
} 

कौन सा ही है के रूप में:

try 
{ 
    // blah 
} 
finally 
{ 
    File.Delete(tempFileName); 
} 

बस इसे एक दायरा छोड़ने पर निष्पादित करने के लिए कुछ कोड प्राप्त करने के तरीके के बारे में सोचें।

+0

अरे, निपटान तर्क को पैरामीटर करना एक दिलचस्प विचार है। मुझे कल्पना है कि ऐसा करने के कई तरीके हैं। ठंडा। –

+0

उपर्युक्त चरम पर ले लिया गया है, इसमें बहुत कुछ नहीं है! लेकिन हाँ शायद कई आधे रास्ते के मामले हैं। आपको यह चर्चा दिलचस्प मिल सकती है: http://incrediblejourneysintotheknown.blogspot.com/2009/02/functional-replacement-for-using.html –

1

यदि कोई वर्ग IDISposable लागू करता है, तो शायद यह अच्छे कारण के लिए है। इसलिए IDISposable लागू करने वाली कोई भी कक्षा का निपटान किया जाना चाहिए।

1

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

मुझे कोड के अनुभागों को सरल बनाने के लिए इसका उपयोग करना पसंद है जहां डिस्पोजेबल ऑब्जेक्ट्स का उपयोग बहुत अधिक होता है यानी फाइलों और ग्राफिक्स ऑब्जेक्ट्स जैसे संसाधनों तक पहुंच और मैं यह सुनिश्चित करना चाहता हूं कि मैं संसाधन का निपटान संभालना न भूलूं वस्तु।

0

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