স্ট্রিম অবজেক্টের জন্য আমাকে ক্লোজ () বা ডিসপোজ () কল করা উচিত?


151

যেমন ক্লাস Stream, StreamReader, StreamWriterইত্যাদি কার্যকরী IDisposableইন্টারফেস। এর অর্থ, আমরা Dispose()এই শ্রেণীর বস্তুগুলিতে পদ্ধতিটি কল করতে পারি । তারা publicবলা একটি পদ্ধতি সংজ্ঞায়িত করেছেন Close()। এখন এটি আমাকে বিভ্রান্ত করছে, আমি যখন বস্তুর সাথে কাজ করলাম তখন আমাকে কী কল করা উচিত? আমি যদি দুজনকে ফোন করি?

আমার বর্তমান কোডটি হ'ল:

using (Stream responseStream = response.GetResponseStream())
{
   using (StreamReader reader = new StreamReader(responseStream))
   {
      using (StreamWriter writer = new StreamWriter(filename))
      {
         int chunkSize = 1024;
         while (!reader.EndOfStream)
         {
            char[] buffer = new char[chunkSize];
            int count = reader.Read(buffer, 0, chunkSize);
            if (count != 0)
            {
               writer.Write(buffer, 0, count);
            }
         }
         writer.Close();
      }
      reader.Close();
   }
}

যেমন আপনি দেখতে পাচ্ছেন, আমি using()কনস্ট্রাক্টস লিখেছি , যা Dispose()প্রতিটি বস্তুর উপর স্বয়ংক্রিয়ভাবে পদ্ধতি কল করে। তবে আমি Close()পদ্ধতিগুলি কল । এটা কি ঠিক?

স্ট্রিম অবজেক্ট ব্যবহার করার সময় দয়া করে আমাকে সেরা অনুশীলনের পরামর্শ দিন। :-)

এমএসডিএন উদাহরণ using()কনস্ট্রাক্টস এবং কল Close()পদ্ধতি ব্যবহার করে না :

এটা কি ভালো?


আপনি যদি রিসার্পার ব্যবহার করছেন তবে আপনি এটি প্যাটার ক্যাটালগের মধ্যে একটি "অ্যান্টিপ্যাটার্ন" হিসাবে সংজ্ঞায়িত করতে পারেন। রিশার্পার প্রতিটি সংজ্ঞা আপনার সংজ্ঞা সম্পর্কিত ত্রুটি / ইঙ্গিত / সতর্কতা হিসাবে চিহ্নিত করবে। পুনঃশার্পার কীভাবে এই জাতীয় ঘটনার জন্য কুইকফিক্স প্রয়োগ করতে পারে তা নির্ধারণ করাও সম্ভব।
থর্স্টন হ্যানস

3
কেবলমাত্র একটি টিপ: আপনি একাধিক ডিসপোজযোগ্য আইটেনগুলির জন্য এর মতো স্টেটিং স্টেটমেন্টটি ব্যবহার করতে পারেন: (স্ট্রিম রেসপন্স = প্রতিক্রিয়া etGetResponseStream ()) (স্ট্রিমরিডার রিডার = নতুন স্ট্রিম রিডার (রেসপন্স)) ব্যবহার করে (স্ট্রিম রাইটার লেখক = নতুন স্ট্রিম রাইটার (ফাইলের নাম)) {//... কিছু কোড}
লাট্রোভা


আপনার নিজের বিবৃতি ব্যবহারের মতো বাসা বাঁধার দরকার নেই যে আপনি এগুলিকে একে অপরের উপরে স্ট্যাক করে রাখতে পারেন এবং একটি বন্ধনী সেট করতে পারেন। অন্য পোস্টে, আমি একটি কোড স্নিপেটের জন্য একটি সম্পাদনার পরামর্শ দিয়েছিলাম যা যদি আপনি "কোড তীর" সন্ধান করতে এবং ঠিক করতে চান তবে সেই কৌশলটির সাথে বিবৃতি ব্যবহার করা উচিত ছিল: stackoverflow.com/questions/5282999/…
টিমোথি গনজালেজ

2
@ সানকাট 2000 আপনার কাছে স্টেটমেন্ট ব্যবহার করে একাধিক থাকতে পারে তবে সেগুলি নীড় নয় এবং পরিবর্তে এগুলি স্ট্যাক করুন। আমি এই কোন ধরনের সীমিত মত বাক্য গঠন মানে না: using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream()) { }। আমার অর্থ এই যেখানে আপনি প্রকারটি নতুন করে সংজ্ঞায়িত করতে পারেন:using (MemoryStream ms = new MemoryStream()) using (FileStream fs = File.OpenRead("c:\\file.txt")) { }
তীমথিয় গনজালেজ

উত্তর:


101

রিফ্লেক্টর.নাইটে একটি দ্রুত জাম্প দেখায় যে Close()পদ্ধতিটি চালু StreamWriterরয়েছে:

public override void Close()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

এবং StreamReaderহ'ল:

public override void Close()
{
    this.Dispose(true);
}

Dispose(bool disposing)মধ্যে ওভাররাইড StreamReaderহয়:

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            this.stream = null;
            /* deleted for brevity */
            base.Dispose(disposing);
        }
    }
}

StreamWriterপদ্ধতি অনুরূপ।

সুতরাং, কোড পড়া এটা স্পষ্ট যে আপনি কল করতে পারেন Close()& Dispose()মত এবং কোন অনুক্রমে আপনার মত প্রায়ই স্ট্রিমগুলিতে। এটি কোনওভাবেই আচরণটি পরিবর্তন করবে না।

সুতরাং এটি থাকুক বা না থাকুক এটা ব্যবহার করা আরো পাঠযোগ্য আসে নিচে Dispose(), Close()এবং / অথবা using ( ... ) { ... }

আমার ব্যক্তিগত পছন্দটি হ'ল using ( ... ) { ... }সম্ভব হলে সর্বদা ব্যবহার করা উচিত কারণ এটি আপনাকে "কাঁচি দিয়ে না চালাতে" সহায়তা করে।

তবে, যদিও এটি সংশোধন করতে সহায়তা করে এটি পাঠযোগ্যতা হ্রাস করে। সি # তে ইতিমধ্যে কোঁকড়া ধনুর্বন্ধনী বন্ধ করার আধিক্য রয়েছে সুতরাং আমরা কীভাবে জানি যে কোনটি প্রবাহে বন্ধটি সম্পাদন করে?

সুতরাং আমি মনে করি এটি করা ভাল:

using (var stream = ...)
{
    /* code */

    stream.Close();
}

এটি কোডের আচরণকে প্রভাবিত করে না, তবে এটি পাঠযোগ্যতার সহায়তা করে।


20
" সি # তে ইতিমধ্যে কোঁকড়া ধনুর্বন্ধনী বন্ধ করার আধিক্য রয়েছে তাই আমরা কীভাবে জানব যে কোনটি আসলে স্ট্রিমের ঘনিষ্ঠতা সম্পাদন করে? " আমি মনে করি না যে এটি একটি বড় সমস্যা: প্রবাহটি "সঠিক সময়ে" বন্ধ হয়ে গেছে, অর্থাত্ যখন পরিবর্তনশীল সুযোগের বাইরে চলে যায় এবং আর প্রয়োজন হয় না।
হেইনজি

110
হুম, না, এটাই "কেন হেক সে দু'বার বন্ধ করছে ??" পড়ার সময় স্পিড বাম্প।
হ্যানস প্যাস্যান্ট

57
অপ্রয়োজনীয় Close()কলটির সাথে আমি একমত নই । যদি কম অভিজ্ঞ কেউ কোডটি দেখেন এবং usingতিনি কী করবেন সে সম্পর্কে জানেন না : 1) এটি সন্ধান করুন এবং শিখুন , বা 2) অন্ধভাবে একটি Close()ম্যানুয়ালি যুক্ত করুন। যদি সে 2 বাছাই করে), সম্ভবত অন্য কোনও বিকাশকারী অপ্রয়োজনীয় দেখতে পাবে Close()এবং "চকিং" এর পরিবর্তে, অভিজ্ঞ অভিজ্ঞ বিকাশকারীকে নির্দেশ দিন। আমি অনভিজ্ঞ বিকাশকারীদের পক্ষে জীবনকে কঠিন করার পক্ষে নই, তবে আমি তাদের অভিজ্ঞ বিকাশকারীদের রূপান্তর করার পক্ষে।
আর মার্টিনহো ফার্নান্দেস

14
যদি আপনি + ক্লোজ () ব্যবহার করে এবং চালু / বিশ্লেষণ চালু করেন তবে আপনি "সতর্কতা: সিএ 2202: মাইক্রোসফ্ট। ব্যবহার: অবজেক্ট 'চ' পদ্ধতিটি 'ফু (স্ট্রিং)' তে একাধিক বার নিষ্পত্তি করতে পারেন a সিস্টেম তৈরি করা এড়াতে। অবজেক্টডিস্পোজড এক্সেক্সশনটি আপনাকে কোনও বস্তুতে একাধিকবার ডিসপোজ কল করতে হবে না: লাইন: 41 "ডকুমেন্টেশন এবং / বিশ্লেষণ অনুযায়ী ক্লোজ এবং ডিসপোজ কল করার ক্ষেত্রে বর্তমান বাস্তবায়ন ঠিক আছে, তবে এটি ঠিক নেই এবং ভবিষ্যতের সংস্করণগুলিতে পরিবর্তন হতে পারে। নেট।
marc40000

4
ভাল উত্তর জন্য +1। আরেকটি বিষয় বিবেচনা করা উচিত। // বন্ধ হওয়ার মতো বা বন্ধ হিসাবে আমি যেমন মন্তব্য করি না কেন, নবাগত হওয়ার কারণে, কোনও ক্লোজিং ব্রেস পরিষ্কার না হওয়ার পরে আমি একটি লাইনার যুক্ত করি। উদাহরণস্বরূপ একটি দীর্ঘ শ্রেণীর ক্ষেত্রে আমি চূড়ান্ত সমাপ্তি বন্ধনী পরে // এন্ড নেমস্পেস XXX এবং দ্বিতীয় চূড়ান্ত সমাপ্তি বন্ধনী পরে // শেষ শ্রেণীর YYY যুক্ত করব। এটি কি মন্তব্যগুলির জন্য নয়। উৎসুক. :) নবাগত হিসাবে আমি এই জাতীয় কোড দেখেছি, হেনসে কেন আমি এখানে এসেছি। আমি "দ্বিতীয় বন্ধের প্রয়োজন কেন" প্রশ্নটি জিজ্ঞাসা করেছি। আমি মনে করি কোডের অতিরিক্ত লাইনগুলি স্পষ্টতা যুক্ত করতে পারে না। দুঃখিত।
ফ্রান্সিস রজার্স

51

না, আপনাকে সেই পদ্ধতিগুলি ম্যানুয়ালি কল করা উচিত নয়। শেষে usingব্লক Dispose()পদ্ধতি স্বয়ংক্রিয়ভাবে বলা হয় যেটিতে বিনামূল্যে অপরিচালিত সম্পদ যত্ন নিতে হবে (অন্তত এই ধরনের স্ট্রিম, পাঠকদের / লেখকদের মান .NET ছাত্রলীগের শ্রেণীর জন্য, ...)। সুতরাং আপনি নিজের কোডটিও এভাবে লিখতে পারেন:

using (Stream responseStream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(responseStream))
        using (StreamWriter writer = new StreamWriter(filename))
        {
            int chunkSize = 1024;
            while (!reader.EndOfStream)
            {
                 char[] buffer = new char[chunkSize];
                 int count = reader.Read(buffer, 0, chunkSize);
                 if (count != 0)
                 {
                     writer.Write(buffer, 0, count);
                 }
            }
         }

Close()পদ্ধতি কল Dispose()


1
আমি নিশ্চিত যে আপনার usingপ্রথম responseStreamহওয়ার দরকার নেই যেহেতু এটি মোড়ানো থাকে readerযা পাঠককে নিষ্পত্তি করার পরে এটি বন্ধ হয়ে যাবে তা নিশ্চিত করবে। তবুও +1
ইসাক সাভো

এটি বিভ্রান্তিকর যখন আপনি বলেছেন The Close method calls Dispose... এবং আপনার পোস্টের বাকী অংশগুলিতে, আপনি বোঝাচ্ছেন যে Dispose()কল করবে Close(), আমি পরে ফোনটি ম্যানুয়ালি বলব না। আপনি কি বলছেন যে তারা একে অপরকে ফোন করে?
নওয়াজ

@ নাওয়াজ, আমার পোস্টটি বিভ্রান্তিকর ছিল। ক্লোজ পদ্ধতিটি কেবল নিষ্পত্তি কল করে। আপনার ক্ষেত্রে নিয়ন্ত্রিত সংস্থানগুলি মুক্ত করতে আপনার নিষ্পত্তি করতে হবে। বিবৃতিটি ব্যবহার করে আপনার কোড মোড়ানো দ্বারা নিষ্পত্তি পদ্ধতি বলা হয়।
দারিন দিমিত্রভ

3
ভয়াবহ উত্তর। এটি ধরে নিয়েছে যে আপনি একটি usingব্লক ব্যবহার করতে পারেন । আমি এমন একটি ক্লাস বাস্তবায়ন করছি যা সময়ে সময়ে লেখেন এবং তাই পারে না।
জেজ

5
@ জিজ আপনার ক্লাসের পরে আইডিপোজেবল ইন্টারফেস প্রয়োগ করা উচিত এবং সম্ভবত ক্লোজ () যদি কাছাকাছি অঞ্চলে স্ট্যান্ডার্ড পরিভাষা হয় , যাতে আপনার ক্লাসটি ব্যবহার করে ক্লাসগুলি using(বা, আবার ডিসপোজ প্যাটার্নে যেতে পারে) ব্যবহার করতে পারে ।
ডোরাস

13

ডকুমেন্টেশন বলছে যে এই দুটি পদ্ধতি সমান:

স্ট্রিমরিডার.ক্লোজ : ক্লোজ এর এই বাস্তবায়নটি ডিসপোজ পদ্ধতিটিকে একটি সত্য মান পাস করে বলে।

স্ট্রিম রাইটার.ক্লোজ : ক্লোজের এই বাস্তবায়নটি ডিসপোজ পদ্ধতিটিকে একটি সত্য মান পাস করে বলে।

স্ট্রিম.ক্লোজ : এই পদ্ধতিটি ডিসপোজকে কল করে, সমস্ত সংস্থান প্রকাশ করার জন্য সত্য উল্লেখ করে।

সুতরাং, এই উভয়ই সমানভাবে বৈধ:

/* Option 1, implicitly calling Dispose */
using (StreamWriter writer = new StreamWriter(filename)) { 
   // do something
} 

/* Option 2, explicitly calling Close */
StreamWriter writer = new StreamWriter(filename)
try {
    // do something
}
finally {
    writer.Close();
}

ব্যক্তিগতভাবে, আমি প্রথম বিকল্পটি দিয়ে থাকব, কারণ এতে "শব্দ" কম রয়েছে।


5

উভয় Close()এবং Dispose()পদ্ধতি উভয় সমর্থন করে এমন অনেক শ্রেণিতে দুটি কল সমান হবে be কিছু ক্লাসে, তবে বন্ধ হয়ে গেছে এমন কোনও বস্তু পুনরায় খোলার সম্ভব। পুনরায় খোলার অনুমতি দেওয়ার জন্য এই জাতীয় কিছু শ্রেণীর কিছু সংস্থান বন্ধ থাকার পরেও জীবিত রাখতে পারে; অন্যরা কোনও সংস্থান টিকে থাকতে পারে না Close(), তবে Dispose()পুনরায় খোলার স্পষ্টভাবে নিষেধ করার জন্য একটি পতাকা স্থাপন করতে পারে ।

চুক্তির জন্য IDisposable.Disposeস্পষ্টভাবে আবশ্যক যে কোনও বস্তুতে এটি পুনরায় ব্যবহার করা হবে যা আর কখনও ব্যবহার করা হবে না, এটি সবচেয়ে খারাপ ক্ষতি হতে পারে, সুতরাং আমি উভয়কেই ডাকবে বা না জানুক না কেন, প্রতিটি বস্তুতে IDisposable.Disposeডাকা একটি পদ্ধতি ।Dispose()IDisposableClose()


এফওয়াইআই এখানে এমএসডিএন ব্লগের একটি নিবন্ধ যা ক্লোজ এবং ডিসপোজ মজাদার ব্যাখ্যা করে। ব্লগস.এমএসডন.কম
কিমহিল /

1

এটি একটি পুরানো প্রশ্ন, তবে আপনি এখন প্রতিটি ব্লক করার প্রয়োজন ছাড়াই বিবৃতি ব্যবহার করে লিখতে পারেন। এতে থাকা ব্লকটি শেষ হয়ে গেলে এগুলি বিপরীত ক্রমে নিষ্পত্তি করা হবে।

using var responseStream = response.GetResponseStream();
using var reader = new StreamReader(responseStream);
using var writer = new StreamWriter(filename);

int chunkSize = 1024;
while (!reader.EndOfStream)
{
    char[] buffer = new char[chunkSize];
    int count = reader.Read(buffer, 0, chunkSize);
    if (count != 0)
    {
        writer.Write(buffer, 0, count);
    }
}

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.