2012-04-05 10 views
7

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

public byte[] ReadFile(Stream stream) 
{ 
    byte[] result = null; 

    try 
    { 
     // do something with stream 
     result = <result of operation> 
    } 
    finally 
    { 
     stream.Close(); 
    } 

    return result; 
} 
इस

public byte[] ReadFile(Stream stream) 
{ 
    byte[] result = null; 

    // do something with stream 
    result = <result of operation> 

    return result; 
} 

में बदल गया था मैं सी # करने के लिए करना चाहिए धारा नहीं काफी नया हूँ कर रहे हैं नहीं कर रहा हूँ जब आप इसके साथ समाप्त हो जाते हैं तो बंद हो जाएं?

+0

ऐसा नहीं है कि या तो मामले में यह फायदेमंद अपने 'ReadFile' दस्तावेज़ के लिए के लिए किया जाए या नहीं यह धारा बंद कर देता है है। उदाहरण के लिए, 'स्ट्रीम रीडर' के लिए कन्स्ट्रक्टर जो स्ट्रीम लेता है, विशेष रूप से कहता है कि यह उस स्ट्रीम का निपटान करता है, इसलिए कॉलर को फिर से इसका निपटान नहीं करना चाहिए। – Servy

+0

@ सर्वी: यह कहना अधिक सटीक है कि कॉलर _needn't_ फिर से इसका निपटान नहीं करता है। 'निपटान' का मतलब डिजाइन द्वारा बेवकूफ होना है, इसलिए इसे बार-बार कॉल करना कोई प्रभाव नहीं होना चाहिए। – Douglas

+0

@ डगलस यह जानना अभी भी महत्वपूर्ण है कि कोई विधि 'आईडीस्पोजेबल' में पारित होने का निपटान करती है क्योंकि कॉलर इसका उपयोग करना जारी रख सकता है। यदि आप इसे किसी ऐसे व्यक्ति को पास करते हैं जो इसका निपटारा करता है और आप इसे फिर से उपयोग करते हैं, तो बीएएम! – Servy

उत्तर

11

आम तौर पर पहला संस्करण खराब डिजाइन होगा।

हां, स्ट्रीम बंद होना चाहिए, लेकिन अधिमानतः उसी कोड (उसी विधि) द्वारा इसे खोला जाना चाहिए। इसे चिंताओं को अलग करने के लिए कहा जाता है और इससे गलतियों और भ्रम की संभावना कम होती है।

तो या तो

  • अपने ReadFile() उदाहरण एक string fileName और खोलता है के लिए स्वीकार करता है और स्ट्रीम बंद कर देता है, या
  • आप इसे फोन करने वाले के लिए छोड़ दें।

आपका विधि (2 संस्करण) इस तरह से इस्तेमाल किया जाना चाहिए:

using (var reader = new FileReader(...)) 
{ 
    // maybe some pre-reading 
    var r = ReadFile(reader); 
    // maybe some post-reading 
} 

ध्यान दें कि 2 दृष्टिकोण भी विधि अधिक पुन: प्रयोज्य बना देता है।

+0

इस अर्थ अब बहुत बहुत धन्यवाद मैं वापस चला गया और देखा और महसूस किया कि मैं पहले से ही कॉल एक ऐसा लगा कि एकमात्र कारण यह करने के लिए नहीं था का उपयोग कर, ऐसा लगता है कि आप अपनी आँखें खोल दिया में लिपटे था बनाता है। धन्यवाद। –

+0

@Henk Holterman: मैं चिंताओं की जुदाई पर अपने बयान से पूरी तरह सहमत हूँ, लेकिन दुर्भाग्य से इस डिजाइन में कम से कम कंस्ट्रक्टर्स के मामले में, नेट से टूटा हुआ प्रतीत होता। पाठक (जैसे 'स्ट्रीम रीडर') के निर्माता को 'स्ट्रीम' पास करना, लेखक (जैसे 'बाइनरीवाइटर'), या यहां तक ​​कि एक और स्ट्रीम (जैसे' जीज़िपस्ट्रीम') मूल पाठ को डिस्पोजेड करने का कारण बनती है जब अन्य पाठक/लेखक/धारा है। – Douglas

+0

@ डगलस - हाँ और यह एक बहुत बहस डिजाइन है। कभी-कभी सुविधाजनक, कभी-कभी एक बुरा आश्चर्य। लेकिन कम से कम यह वस्तुओं के बीच स्वामित्व को स्थानांतरित कर रहा है, तरीकों के बीच नहीं। –

6

इस प्रश्न पर कोई सही जवाब नहीं है, क्योंकि यह आपके ऐप आर्किटेक्चर पर निर्भर करता है।

मैं कहूंगा कि, हाँ, अगर यह समारोह में stream नहीं बनाई गई है कारण है, लेकिन केवल इस्तेमाल किया, तो यह के समापन की कॉलर पर निर्भर करने देते हैं।

लेकिन मैं दोहराता हूं, यह आपके ऐप आर्किटेक्चर पर निर्भर करता है।

5

दरवाजा खोलने वाले को इसे बंद करने के लिए याद रखना चाहिए।

तो इसे खोलने वाले तरीके में स्ट्रीम को बंद करना बेहतर है।

0

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

using(Stream stream = new ...) 
{ 
    ...call your method 
} 

(या जैसे पाठक यह के निपटान है - लेकिन यह अनुशंसित है कि आप या तो मामले में कुछ इस तरह करते हैं - बराबर उपयोग कर रहा है एक 'finally' ब्लॉक, लेकिन एक ही चीज़ पर उबाल जाता है)

... मूल रूप से कॉलिंग फ़ंक्शन कभी नहीं जानता होगा कि आपने इसे 'अंदर' या नहीं - जब तक यह क्रैश नहीं हो जाता है। यदि 'दोनों भाग' इस तरह से कुछ पर सहमत हैं, तो यह अभी भी स्वीकार्य नहीं है लेकिन अपूर्ण हो सकता है।

3

आमतौर पर स्ट्रीम के निर्माता भी इसे बंद करने के लिए, आदर्श एक का उपयोग कर ब्लॉक के साथ यह निपटाने द्वारा किया जाना चाहिए:

using (var myStream = getMeAStream()) { 
    ReadFile(myStream); 

    // If you want to be really sure it is closed: 
    myStream.Close(); 
    // Probably not neccessary though, since all 
    // implementations of Stream should Close upon Disposal 
} 
1

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

कारण यह है कि एक और ऑपरेशन (जैसे रीसेट या किसी अन्य पढ़ने) इस समारोह को बाहर किया जा करना पड़ सकता है और यदि आप इसे बंद आप एक अपवाद का कारण होगा है।

मैं जब तक अंत में किसी ने मुझे की बात सुनी एक दिन यह कई बार की तरह कोड refactor करने के लिए इस्तेमाल किया।

मैं, कम से कम एक गंभीर कोड की इस तरह की वजह से बग देखा है इसलिए सामान्य

0

में अपनी एक बुरा विचार यह बस एक सी # समस्या नहीं है। फ़ंक्शन "रीडफाइल" के कॉल के बाद आपको अन्य परिचालनों के लिए स्ट्रीम का उपयोग करने की आवश्यकता है? यदि आप फ़ाइल को पढ़ने के बाद स्ट्रीम बंद करना चुन सकते हैं। यह बेहतर समापन धाराओं जब आप उन्हें उपयोग करने के लिए खत्म है, लेकिन आम तौर पर मैं उन्हें एक ही संदर्भ में बंद करने के लिए की तुलना में उन्हें खोलता है पसंद करते हैं, क्योंकि यह वहाँ जगह है जहाँ आप जानते हैं कि यदि आप अन्य ऑपरेशन के लिए धारा की जरूरत है:

Stream s = open_the_stream() 
try { 
    ReadFile(s)... 
} finally { 
    s.Close(); 
} 

किसी भी तरह से, जब आप उन्हें उपयोग करने के लिए समाप्त करते हैं तो बंद स्ट्रीम।

+0

धन्यवाद यह स्थिति को और स्पष्ट करता है –

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