রুবিতে শুরু, উদ্ধার এবং নিশ্চিতকরণ?


547

আমি সম্প্রতি রুবিতে প্রোগ্রামিং শুরু করেছি এবং আমি ব্যতিক্রম হ্যান্ডলিংয়ের দিকে তাকিয়ে আছি।

আমি ভাবছিলাম যে সি # তে ensureরুবি সমান finally? আমার উচিত:

file = File.open("myFile.txt", "w")

begin
  file << "#{content} \n"
rescue
  #handle the error here
ensure
  file.close unless file.nil?
end

বা আমার এই করা উচিত?

#store the file
file = File.open("myFile.txt", "w")

begin
  file << "#{content} \n"
  file.close
rescue
  #handle the error here
ensure
  file.close unless file.nil?
end

নেই ensureকোন ব্যাপার এমনকি যদি একটি ব্যতিক্রম উত্থাপিত হয় না কি, বলা না?


1
দুটোই ভাল না। একটি নিয়ম হিসাবে, বাহ্যিক সংস্থানগুলির সাথে কাজ করার সময়, আপনি সর্বদা চান যে উত্স খোলার ` beginব্লকের ভিতরে থাকা ।
এখন

উত্তর:


1181

হ্যাঁ, ensureকোডটি সর্বদা মূল্যায়ন করা হয় তা নিশ্চিত করে। এ কারণেই এটি বলা হয় ensure। সুতরাং, এটি জাভা এবং সি # এর সমতুল্য finally

সাধারণ প্রবাহ begin/ rescue/ else/ ensure/ এর endমতো দেখায়:

begin
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
rescue SomeOtherException => some_other_variable
  # code that deals with some other exception
else
  # code that runs only if *no* exception was raised
ensure
  # ensure that this code always runs, no matter what
  # does not change the final value of the block
end

আপনি ছেড়ে যেতে পারেন rescue, ensureবা else। আপনি নিজের ব্যতিক্রম হ্যান্ডলিং কোডে ব্যতিক্রমটি পরীক্ষা করতে সক্ষম হবেন না এমন ক্ষেত্রে আপনি ভেরিয়েবলগুলিও ছেড়ে দিতে পারেন। (ভাল, আপনি উত্থাপিত সর্বশেষ ব্যতিক্রমটি অ্যাক্সেস করতে সর্বদা বিশ্বব্যাপী ব্যতিক্রম ভেরিয়েবলটি ব্যবহার করতে পারেন তবে এটি খানিকটা হ্যাকি)) এবং আপনি ব্যতিক্রম শ্রেণিটি ছেড়ে দিতে পারেন, সেক্ষেত্রে উত্তরাধিকারসূত্রে প্রাপ্ত সমস্ত ব্যতিক্রম StandardErrorধরা পড়বে। (দয়া করে নোট অর্থ কি এই যে করেন না, যে সব ব্যতিক্রম ধরা হয়, কারণ সেখানে ব্যতিক্রম যার দৃষ্টান্ত রয়েছে Exceptionকিন্তু StandardError। প্রায় খুব তীব্র ব্যতিক্রম যে আপস যেমন প্রোগ্রাম অখণ্ডতা SystemStackError, NoMemoryError, SecurityError, NotImplementedError, LoadError, SyntaxError, ScriptError, Interrupt,SignalExceptionবা SystemExit।)

কিছু ব্লক অন্তর্ভুক্ত ব্যতিক্রম ব্লক গঠন করে। উদাহরণস্বরূপ, পদ্ধতির সংজ্ঞাগুলি স্পষ্টতই ব্যতিক্রম ব্লকগুলিও তাই লেখার পরিবর্তে

def foo
  begin
    # ...
  rescue
    # ...
  end
end

আপনি শুধু লিখুন

def foo
  # ...
rescue
  # ...
end

অথবা

def foo
  # ...
ensure
  # ...
end

classসংজ্ঞা এবং moduleসংজ্ঞাগুলির ক্ষেত্রেও একই প্রযোজ্য ।

যাইহোক, আপনি যে নির্দিষ্ট ক্ষেত্রে সম্পর্কে জিজ্ঞাসা করছেন সে ক্ষেত্রে আসলে আরও অনেক ভাল প্রতিমা রয়েছে। সাধারণভাবে, আপনি যখন শেষে এমন কোনও সংস্থান নিয়ে কাজ করতে চান যা আপনাকে পরিষ্কার করতে হবে তখন আপনি কোনও পদ্ধতিতে একটি ব্লক পাস করে যা আপনার জন্য সমস্ত ক্লিনআপ করে। এটি usingসি # এর একটি ব্লকের মতোই , রুবি আসলেই যথেষ্ট শক্তিশালী যে আপনাকে মাইক্রোসফ্টের উচ্চ পুরোহিতদের পর্বত থেকে নেমে আসা উচিত নয় এবং দয়া করে আপনার জন্য তাদের সংকলকটি পরিবর্তন করতে হবে না। রুবিতে আপনি কেবল এটি প্রয়োগ করতে পারেন:

# This is what you want to do:
File.open('myFile.txt', 'w') do |file|
  file.puts content
end

# And this is how you might implement it:
def File.open(filename, mode='r', perm=nil, opt=nil)
  yield filehandle = new(filename, mode, perm, opt)
ensure
  filehandle&.close
end

এবং আপনি কী জানেন: এটি মূল লাইব্রেরিতে ইতিমধ্যে উপলব্ধ File.open। তবে এটি একটি সাধারণ প্যাটার্ন যা আপনি নিজের কোডটিতেও ব্যবহার করতে পারেন, যেকোন ধরণের রিসোর্স ক্লিনআপ ( usingসি # à লা ) বা লেনদেনের জন্য বা আপনি যা ভাবেন তা বিবেচনা করতে পারেন।

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


বিটিডাব্লু: আধুনিক সি # usingতে আসলে অতিরিক্ত অতিরিক্ত, কারণ আপনি রুবি স্টাইলের রিসোর্স ব্লকগুলি নিজেকে ব্লক করতে পারেন:

class File
{
    static T open<T>(string filename, string mode, Func<File, T> block)
    {
        var handle = new File(filename, mode);
        try
        {
            return block(handle);
        }
        finally
        {
            handle.Dispose();
        }
    }
}

// Usage:

File.open("myFile.txt", "w", (file) =>
{
    file.WriteLine(contents);
});

81
নোট করুন, যদিও ensureবিবৃতিগুলি সর্বশেষে কার্যকর করা হয়, তারা রিটার্ন মান নয়।
ক্রিস

30
আমি এসও এর মতো সমৃদ্ধ অবদানগুলি দেখতে পছন্দ করি। এটি ওপিতে যা জিজ্ঞাসা করেছিল তার উপরে এবং অতিক্রম করে এটি আরও অনেক বিকাশকারীদের জন্য প্রযোজ্য, তবুও এখনও বিষয়টিতে রয়েছে। আমি এই উত্তর + সম্পাদনা থেকে কিছু জিনিস শিখেছি। "হ্যাঁ, ensureযাই হোক না কেন ডাকা হয় না " লেখার জন্য আপনাকে ধন্যবাদ ।
ডেনিস 11

3
দ্রষ্টব্য, নিশ্চিত যে সম্পূর্ণ করার গ্যারান্টিযুক্ত হয় না। কোনও থ্রেডের ভিতরে আপনার যেখানে শুরু / নিশ্চিত / শেষ রয়েছে তার ক্ষেত্রে নিন এবং যখন নিশ্চিত ব্লকের প্রথম লাইনটি কল করা হবে তখন আপনি থ্রেড.কিল কল করবেন। এটি বাকী বিশ্লেষণগুলি কার্যকর না করার কারণ ঘটায়।
টেডি

5
@ টেডি: নিশ্চিতকরণ কার্যকর করার গ্যারান্টিযুক্ত, সম্পূর্ণ করার গ্যারান্টিযুক্ত নয়। আপনার উদাহরণটি ওভারকিল - নিশ্চিত ব্লকের অভ্যন্তরে একটি সাধারণ ব্যতিক্রম এটির পাশাপাশি বেরিয়ে আসবে।
মার্টিন কোনেকেনি

3
এছাড়াও নোট করুন যে কোন গ্যারান্টি নেই বলা হয়। আমি সিরিয়াস। একটি পাওয়ার আউটেজ / হার্ডওয়্যার ত্রুটি / ওএস ক্র্যাশ হতে পারে, এবং যদি আপনার সফ্টওয়্যারটি সমালোচনা করে তবে এটিও বিবেচনা করা দরকার।
এডওয়ার্ডএম

37

এফওয়াইআই, এমনকি যদি rescueবিভাগটিতে একটি ব্যতিক্রম পুনরায় উত্থাপিত হয় , ensureকোডটি কার্যকর করার পরে পরবর্তী ব্যতিক্রম হ্যান্ডলারটি চালিয়ে যাওয়ার আগে এই ব্লকটি কার্যকর করা হবে। এই ক্ষেত্রে:

begin
  raise "Error!!"
rescue
  puts "test1"
  raise # Reraise exception
ensure
  puts "Ensure block"
end

14

আপনি যদি কোনও ফাইল বন্ধ রয়েছে তা নিশ্চিত করতে চান আপনার ব্লক ফর্মটি ব্যবহার করা উচিত File.open:

File.open("myFile.txt", "w") do |file|
  begin
    file << "#{content} \n"
  rescue
  #handle the error here
  end
end

3
আমার ধারণা আপনি যদি ত্রুটিটি পরিচালনা করতে না চান তবে কেবল এটি উত্থাপন করেন, এবং ফাইল হ্যান্ডেলটি বন্ধ করুন, আপনার এখানে আরম্ভ করার দরকার নেই?
রজারডপ্যাক


5

হ্যাঁ, ensureনিশ্চিত করে যাতে আপনি প্রয়োজন হবে না এটা, প্রত্যেক সময় চালানো হয় file.closebeginব্লক।

যাইহোক, পরীক্ষার একটি ভাল উপায় হ'ল:

begin
  # Raise an error here
  raise "Error!!"
rescue
  #handle the error here
ensure
  p "=========inside ensure block"
end

কোনও ব্যতিক্রম থাকলে "========== ভিতরে নিশ্চিত ব্লক" মুদ্রিত হবে কিনা তা পরীক্ষা করে দেখতে পারেন। তারপরে আপনি ত্রুটি উত্থাপনকারী বিবৃতিটি মন্তব্য করতে পারেন এবং ensureকিছু মুদ্রিত হয়েছে কিনা তা দেখে বিবৃতিটি কার্যকর করা হয়েছে কিনা তা দেখতে পারেন।


4

এজন্য আমাদের প্রয়োজন ensure:

def hoge
  begin
    raise
  rescue  
    raise # raise again
  ensure  
    puts 'ensure' # will be executed
  end  
  puts 'end of func' # never be executed
end  

4

হ্যাঁ, গ্যারান্টিরensure মতো finally যে ব্লকটি কার্যকর হবে । সমালোচনামূলক সংস্থানগুলি সুরক্ষিত রয়েছে তা নিশ্চিত করার জন্য এটি খুব দরকারী eg


তার ক্ষেত্রে ব্যতীত, ফাইলটি বন্ধ হওয়ার কোনও গ্যারান্টি নেই, কারণ File.openঅংশটি সূচনা-নিশ্চিত ব্লকের ভিতরে নেই। কেবলমাত্র file.closeতবে এটি যথেষ্ট নয়।
aker
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.