একটি ব্যবহার ব্লকের মাঝখানে ফিরে


196

কিছুটা এইরকম:

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

আমি বিশ্বাস করি এটি কোনও রিটার্নের বিবৃতিতে উপযুক্ত জায়গা নয়, তাই না?

উত্তর:


194

অন্য বেশিরভাগ সাধারণভাবে উল্লেখ করেছেন যে এটি কোনও সমস্যা নয়।

আপনি যদি কোনও ব্যবহারের বিবৃতিটির মাঝামাঝি ফিরে আসেন এবং অতিরিক্তভাবে ভেরিয়েবলটি ব্যবহার করে ইনটি ফিরিয়ে দেন তবে এটি কেবল আপনার ক্ষেত্রে সমস্যা সৃষ্টি করবে। তবে আবার, আপনি ফিরে না এসে এমনকি কেবল একটি ভেরিয়েবলের রেফারেন্স রাখলেও এটি আপনাকে সমস্যা সৃষ্টি করবে।

using ( var x = new Something() ) { 
  // not a good idea
  return x;
}

ঠিক যেমন খারাপ

Something y;
using ( var x = new Something() ) {
  y = x;
}

1
আপনার উল্লেখ করা পয়েন্টটি সম্পর্কে আমি আমার প্রশ্ন সম্পাদনা করতে চলেছিলাম। ধন্যবাদ।
তাফা

কেন এটি খারাপ তা দয়া করে আমাকে বুঝতে সহায়তা করুন। আমি চিত্র প্রসেসিংয়ের জন্য সাহায্যকারী ফাংশনে অন্য ফাংশনে যে স্ট্রিমটি ব্যবহার করছি তা ফিরিয়ে দিতে চাই। মনে হচ্ছে স্ট্রিমের নিষ্পত্তি হবে যদি আমি এটি করি তবে?
জন শেডলেটস্কি

3
@ জনশেডলেটস্কি এই ক্ষেত্রে আপনার ফাংশন কলটি ব্যবহারের সাথে আবৃত করা উচিত। (স্ট্রিম x = FuncToReturnStream ()) {... using ব্যবহার করার মতো এবং FuncToReturnStream ব্যবহার করে না।
ফেলিক্স কেয়েল

@ জনশেডলেটস্কি আমি নিশ্চিত এটি কারণ যে returnবিবৃতিটি usingকোনও কোড পাথ দ্বারা ব্লকের শেষটিকে অ্যাক্সেসযোগ্য করে তুলেছে । শেষে usingতাই বস্তুর বিন্যস্ত প্রয়োজনে হতে পারে ব্লক চাহিদা দৌড়ে যাবে।
ফেসপাম 42

147

এটা পুরোপুরি ঠিক আছে।

আপনি স্পষ্টতই তা ভাবছেন

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

অন্ধভাবে অনুবাদ করা হয়েছে:

IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();

যা, নিঃসন্দেহে, একটি সমস্যা হতে হবে, এবং হবে usingযার কারণে যে বিবৃতি বরং অর্থহীন --- না এটা কি করে।

সংকলকটি নিশ্চিত করে যে নিয়ন্ত্রণটি ব্লকটি ছাড়ার আগে অবজেক্টটি নিষ্পত্তি হয়ে যায় - এটি ব্লকটি কীভাবে ছাড়বে তা নির্বিশেষে।


7
আমি স্পষ্টতই ছিলাম।
তাফা

দুর্দান্ত উত্তর @ জেমস করান! তবে এটি আমাকে কী কৌতূহলযুক্ত করেছে তাতে এটি কী অনুবাদ করেছে। নাকি তা কেবল আইএল-তে প্রকাশযোগ্য? (যা আমি আগে কখনও পড়ার চেষ্টা করি নি)।
বার্ট

1
@ বার্ট - আমি এটিকে রিটার্ন এক্সপ্রেশনটিকে অস্থায়ী ভেরিয়েবলের মধ্যে মূল্যায়ন করার পরে ডিসপোজটি করার পরে অস্থায়ী ভেরিয়েবলটি ফিরিয়ে আনা হিসাবে মনে করি।
নির্মাতা স্টিভ

@ জামেস কারান উপরে থেকে এখানে, ব্যাকগ্রাউন্ডে কী খুশি তা কেবল আপনিই ব্যাখ্যা করেছেন। অনেক ধন্যবাদ.
সার্কান টিমোইন

@ বার্ট এটি সম্ভবত অনুবাদ হয়েছে: চেষ্টা করুন {... আপনার কোড ...} অবশেষে {x.Dispose (); }
Bip901

94

এটি একেবারে ঠিক - কোনও সমস্যা নেই। কেন আপনি ভুল বিশ্বাস করেন?

একটি ব্যবহারের বিবৃতিটি চেষ্টা / অবশেষে ব্লকের জন্য কেবল সিনট্যাকটিক চিনি এবং গ্রাজনিও যেমন বলেছে তবে চেষ্টা ব্লক থেকেও ফিরে আসাই ভাল fine

রিটার্ন এক্সপ্রেশন মূল্যায়ন করা হবে, তারপরে অবশেষে ব্লকটি কার্যকর করা হবে, তারপরে পদ্ধতিটি ফিরে আসবে।


5
জেমস কুরানের উত্তরটি আমি কী ভাবছিলাম তা ব্যাখ্যা করে।
তাফা

27

এটি পুরোপুরি সূক্ষ্মভাবে কাজ করবে ঠিক যেমন মাঝখানে ফিরে আসবে try{}finally{}


18

এটি সম্পূর্ণ গ্রহণযোগ্য। একটি ব্যবহারের বিবৃতি নিশ্চিত করে যে আইডিস্পোজযোগ্য বস্তুটি যাই হোক না কেন নিষ্পত্তি হবে।

এমএসডিএন থেকে :

ব্যবহারের বিবৃতিটি নিশ্চিত করে যে ডিসপোজ বলা হয় এমনকি যদি আপনি কোনও বস্তুটিতে পদ্ধতি কল করার সময় কোনও ব্যতিক্রম ঘটে। আপনি চেষ্টাটি ব্লকের ভিতরে অবজেক্টটি স্থাপন করে এবং পরে ডিসপোজকে শেষ অবধি কল করে একই ফলাফল অর্জন করতে পারেন; প্রকৃতপক্ষে, কম্পাইলার দ্বারা এভাবেই ব্যবহারের বিবৃতিটি অনুবাদ করা হয়।


14

কোড বেলো দেখায় যে কীভাবে usingকাজ করছে:

private class TestClass : IDisposable
{
   private readonly string id;

   public TestClass(string id)
   {
      Console.WriteLine("'{0}' is created.", id);
      this.id = id;
   }

   public void Dispose()
   {
      Console.WriteLine("'{0}' is disposed.", id);
   }

   public override string ToString()
   {
      return id;
   }
}

private static TestClass TestUsingClose()
{
   using (var t1 = new TestClass("t1"))
   {
      using (var t2 = new TestClass("t2"))
      {
         using (var t3 = new TestClass("t3"))
         {
            return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
         }
      }
   }
}

[TestMethod]
public void Test()
{
   Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}

আউটপুট:

't1' তৈরি হয়।
't2' তৈরি হয়।
't3' তৈরি হয়।
'টি 1, টি 2, টি 3 থেকে তৈরি' তৈরি হয়।
't3' নিষ্পত্তি করা হয়।
'টি 2' নিষ্পত্তি করা হয়।
'টি 1' নিষ্পত্তি করা হয়।

নিষ্পত্তি ফিরতি বিবৃতি পরে বলা হয় কিন্তু ফাংশন থেকে প্রস্থান আগে।


1
দয়া করে মনে রাখবেন যে কিছু সি # অবজেক্টগুলি একটি কাস্টম ফ্যাশনে নিষ্পত্তি হয়, উদাহরণস্বরূপ, ডাব্লুসিএফ ক্লায়েন্টগুলি উপরের রিটার্নের মতো ব্যবহারযোগ্য বিবৃতি "
ডিসপোজড

-4

সম্ভবত এটি 100% সত্য নয় যে এটি গ্রহণযোগ্য ...

আপনি যদি ব্যবহার করে বাসা বেঁধে এবং কোনও নেস্টেডের মধ্যে থেকে ফিরে আসেন তবে এটি নিরাপদ নাও হতে পারে।

এটি একটি উদাহরণ হিসাবে নিন:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
            return memoryStream.ToArray();
        }
    }
}

আমি সিএসভি হিসাবে আউটপুট হওয়ার জন্য একটি ডেটা টেবিল দিয়ে যাচ্ছিলাম। মাঝখানে ফিরে আসার সাথে সাথে, এটি স্রোতে সমস্ত সারি লিখছিল, তবে আউটপুটযুক্ত সিএসভি সর্বদা একটি সারি (বা একাধিক, বাফারের আকারের উপর নির্ভর করে) হারিয়েছিল। এটি আমাকে জানিয়েছিল যে কিছু সঠিকভাবে বন্ধ করা হচ্ছে না।

পূর্ববর্তী সমস্ত ব্যবহার সঠিকভাবে নিষ্পত্তি হয়েছে তা নিশ্চিত করা সঠিক উপায়:

using (var memoryStream = new MemoryStream())
{
    using (var textwriter = new StreamWriter(memoryStream))
    {
        using (var csv = new CsvWriter(textwriter))
        {
            //..write some stuff to the stream using the CsvWriter
        }
    }

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