যদি আমি একটি চেষ্টা ব্লকের কোনও মান ফেরত দেব তবে শেষ অবধি কোডটি কি আগুনে জ্বলে উঠবে?


237

আমি বন্ধুর জন্য কিছু কোড পর্যালোচনা করছি এবং বলব যে সে চেষ্টা করে অবশেষে একটি ব্লকের অভ্যর্থনা বিবরণী ব্যবহার করছিল। বাকি চেষ্টা ব্লক না করেও কি শেষ অবধি বিভাগের কোডটি এখনও চালু আছে?

উদাহরণ:

public bool someMethod()
{
  try
  {
    return true;
    throw new Exception("test"); // doesn't seem to get executed
  }
  finally
  {
    //code in question
  }
}


এখানে পরিচালিত হওয়ার অর্থ: ধরা পড়ে। এমনকি আপনার গ্লোবাল হ্যান্ডলারের একটি খালি ক্যাচ ব্লকই যথেষ্ট। : এছাড়াও, ব্যতিক্রম যে পরিচালনা করা যাবে না হয় StackOverflowException, ExecutionEngineExceptionসেই কিছু। এবং যেহেতু এগুলি পরিচালনা করা finallyযায় না , তাই চালানো হবে না।
আবেল

8
@ আবেল: আপনি অন্যরকম পরিস্থিতি নিয়ে কথা বলছেন বলে মনে হচ্ছে। এই প্রশ্নটি একটি ব্লকে ফিরে আসার বিষয়ে try। আকস্মিক প্রোগ্রাম বাতিল সম্পর্কে কিছুই নেই।
জন স্কিটি

6
@ আবেল: "ব্যতিক্রমের পরে ফিরে" বলতে আপনার অর্থ কী তা আমি নিশ্চিত নই, তবে এখানে এ সম্পর্কে জিজ্ঞাসা করা হচ্ছে বলে মনে হয় না। কোডটি দেখুন - tryব্লকের প্রথম বিবৃতিটি একটি returnবিবৃতি। (এই ব্লকের দ্বিতীয় বিবৃতিটি অ্যাক্সেসযোগ্য নয় এবং এটি একটি সতর্কবার্তা উত্পন্ন করবে))
জন স্কিপ

4
@ আবেল: প্রকৃতপক্ষে, এবং যদি প্রশ্নটি "শেষ অবধি উইল কোডটি সর্বদা প্রতিটি পরিস্থিতিতে কার্যকর করা হত" তবে তা প্রাসঙ্গিক হত। তবে এটাই বলা হয়নি।
জন স্কিটি

উত্তর:


265

সহজ উত্তর: হ্যাঁ


9
@ এডি: উম, আমি এর সাথে পটভূমির থ্রেডগুলির কী করণীয় তা দেখতে পাচ্ছি না। মূলত, পুরো প্রক্রিয়াটি বাতিল না হলে, finallyব্লকটি কার্যকর করা হবে।
জন স্কিটি

3
দীর্ঘ উত্তরটি হ'ল স্ট্যাক ওভারফ্লো, আউট অফ মেমরি ব্যতিক্রম, কোনও ধরণের শক্ত ক্র্যাশ, বা কেউ যদি সঠিক সময়ে আপনার মেশিনকে প্লাগ করে দেয় তবে বিপর্যয়কর কিছু ঘটলে অবশেষে চালানোর জন্য আপনি শেষ পর্যন্ত কোনও ব্লক পাবেন না if । তবে সমস্ত অভিপ্রায় এবং উদ্দেশ্যগুলির জন্য, আপনি যদি খুব খুব ভুল কিছু না করেন তবে শেষ অবধি সর্বদা অব্যাহত থাকবে।
অ্যান্ড্রু রোলিংস

যদি কোনও কারণে চেষ্টা করার আগে কোড ব্যর্থ হয় তবে আমি লক্ষ্য করেছি যে অবশেষে এখনও কার্যকর হয়ে গেছে।
সেক্ষেত্রে

200

সাধারণত, হ্যাঁ অবশেষে বিভাগটি ব্যতিক্রম বা রিটার্ন বিবৃতি সহ যা কিছু ঘটবে তা কার্যকর করার গ্যারান্টিযুক্ত। এই নিয়মের ব্যতিক্রম থ্রেডে ঘটে যাওয়া একটি অবিচ্ছিন্ন ব্যতিক্রম ( OutOfMemoryException,StackOverflowException ) এ

সেই পরিস্থিতিতে async ব্যতিক্রম এবং নির্ভরযোগ্য কোড সম্পর্কে আরও জানতে, সীমাবদ্ধ বাস্তবায়ন অঞ্চলগুলি সম্পর্কে পড়ুন ।


154

এখানে একটি ছোট পরীক্ষা:

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("before");
        Console.WriteLine(test());
        Console.WriteLine("after");
    }

    static string test()
    {
        try
        {
            return "return";
        }
        finally
        {
            Console.WriteLine("finally");
        }
    }
}

ফলাফল হলো:

before
finally
return
after

10
@ কোডবেল্যান্ড: WriteLineপদ্ধতি কলের ফলাফলের জন্য প্রকৃতপক্ষে সঞ্চালিত হওয়ার সাথে এটি করতে হবে । এক্ষেত্রে returnকল পদ্ধতিগুলির ফলাফল নির্ধারণ করে, অবশেষে কনসোলটিতে লিখে দেয় - পদ্ধতিটি প্রস্থান হওয়ার আগে। তারপরে WriteLineইন মেইন পদ্ধতিটি রিটার্ন কল থেকে পাঠ্যটি সরিয়ে দেয়।
নোটমি

38

এমএসডিএন থেকে উদ্ধৃতি

পরিশেষে কিভাবে পূর্ববর্তী নির্বিশেষে কোডকে কার্যকর একটি বিবৃতি ব্লক গ্যারান্টি ব্যবহার করা হয় ব্যবহার করে দেখুন ব্লক করা হয় থেকে প্রস্থান


3
ঠিক আছে, মেহরদাদের ব্যতিক্রমী কেসগুলি ছাড়াও, আপনি যদি একটি ট্রাই ব্লকে ডিবাগ করছেন এবং অবশেষে ডিবাগিং বন্ধ করেন তবে শেষ পর্যন্ত ডাকা হবে না :)। জীবনে কোনও কিছুই গ্যারান্টিযুক্ত নয়, মনে হয়।
স্টুয়ার্টএলসি

1
এমএসডিএন থেকে উদ্ধৃত করা বেশ নয় : তবে, ব্যতিক্রমটি যদি নিয়ন্ত্রণহীন হয় তবে অবশেষে ব্লকটি কার্যকর করা কীভাবে ব্যতিক্রমটি অনিচ্ছাকৃত অপারেশনকে ট্রিগার করা হয় তার উপর নির্ভর করে। এটি, আপনার কম্পিউটার কীভাবে সেট আপ হয় তার উপর নির্ভর করে।
আবেল

1
@ আবেল এখানে একটি গুরুত্বপূর্ণ বিষয় তৈরি করেছেন। প্রত্যেকে দেখতে পাবে যে কীভাবে অবশেষে ব্লক কার্যকর করা হয় না যদি উদাহরণস্বরূপ প্রোগ্রামটি টাস্ক ম্যানেজারের মাধ্যমে বাতিল করা হয়। তবে এই উত্তরটি যেমন দাঁড়িয়েছে, তেমনি সাধারণ ভুল: finallyবাস্তবে এমনকি সাধারণ প্রোগ্রামগুলির জন্য কোনও কিছুই গ্যারান্টি দেয় না (যা এই ব্যতিক্রমটি ছুঁড়ে ফেলেছিল)
পিটার - মনিকা পুনরায়

19

সাধারণত হ্যাঁ, শেষ পর্যন্ত চলবে।

নিম্নলিখিত তিনটি পরিস্থিতিতে, শেষ পর্যন্ত হবে সর্বদা চালানো হবে:

  1. কোনও ব্যতিক্রম ঘটে না
  2. সিঙ্ক্রোনাস ব্যতিক্রম (সাধারণ প্রোগ্রাম প্রবাহে ব্যতিক্রমগুলি)।
    এটিতে সি.এল.এস. কমপ্লায়েন্ট ব্যতিক্রমগুলি অন্তর্ভুক্ত রয়েছে যা System.Exception এবং নন-সিএলএস অনুবর্তী ব্যতিক্রমগুলি থেকে আসে, যা System.Exception থেকে প্রাপ্ত নয়। নন-সিএলএস সম্মতিযুক্ত ব্যতিক্রমগুলি স্বয়ংক্রিয়ভাবে রানটাইম র্যাপড এক্সেক্সেশন দ্বারা আবৃত হয়। সি # নন-সিএলএস অভিযোগের ব্যতিক্রম ছুঁড়ে ফেলতে পারে না, তবে সি ++ এর মতো ভাষা পারে। সি # এমন একটি ভাষায় লিখিত কোডে কল করতে পারে যা নন-সিএলএস অনুবর্তী ব্যতিক্রম ছুঁড়ে ফেলতে পারে।
  3. অ্যাসিঙ্ক্রোনাস থ্রেডঅবর্টেক্সেপশন
    .NET 2.0 হিসাবে , একটি থ্রেডঅবর্ট এক্সেকশন শেষ পর্যন্ত চলমান থেকে আটকাবে না। থ্রেডআবার্ট এক্সেপশন এখন শেষ অবধি বা তার পরে উত্তোলন করা হয়। শেষ পর্যন্ত সর্বদা চলতে থাকবে এবং থ্রেড অ্যাওর্ট দ্বারা বাধা দেওয়া হবে না, যতক্ষণ না থ্রেড অ্যাওর্ট হওয়ার আগে প্রকৃতপক্ষে চেষ্টাটি প্রবেশ করা হয়েছিল।

নিম্নলিখিত পরিস্থিতিতে, শেষ পর্যন্ত চলবে না:

অ্যাসিঙ্ক্রোনাস স্ট্যাকওভারফ্লোএক্সেপশন।
.NET 2.0 হিসাবে একটি স্ট্যাক ওভারফ্লো প্রক্রিয়াটি শেষ করে দেবে। শেষ অবধি চালানো হবে না, যদি না শেষ অবধি একটি সিইআর (সীমাবদ্ধ নির্বাহ অঞ্চল) করার জন্য আরও বাধা প্রয়োগ করা হয়। সাধারণ ব্যবহারকারী কোডে সিইআর ব্যবহার করা উচিত নয়। এগুলি কেবল সেখানেই ব্যবহার করা উচিত যেখানে ক্লিন-আপ কোডটি সর্বদা চলমান - সমস্ত প্রক্রিয়া যে কোনও উপায়ে স্ট্যাক ওভারফ্লোতে বন্ধ হয়ে যাওয়ার পরে এবং সমস্ত পরিচালিত অবজেক্টগুলি ডিফল্টরূপে পরিষ্কার-আপ করা হবে। সুতরাং, কেবলমাত্র সিইআর প্রাসঙ্গিক হওয়া উচিত সেই প্রক্রিয়াটির বাইরে বরাদ্দকৃত সম্পদগুলির জন্য, যেমন, নিয়ন্ত্রণহীন হ্যান্ডলগুলি।

সাধারণত, পরিচালনা কোডটি ব্যবহারকারীর কোড দ্বারা গ্রাস করার আগে কিছু পরিচালিত শ্রেণীর দ্বারা মোড়ানো হয়। পরিচালিত মোড়কের ক্লাসটি নিয়ন্ত্রিত হ্যান্ডেলটি মোড়ানোর জন্য সাধারণত একটি SafeHandle ব্যবহার করবে। সাফহ্যান্ডল একটি সমালোচনামূলক চূড়ান্তকরণকারী, এবং একটি রিলিজ পদ্ধতি কার্যকর করে যা একটি সিইআর-এ চালিত হয় ক্লিন-আপ কোডটি কার্যকর করার গ্যারান্টি হিসাবে। এই কারণে, আপনার মাধ্যমে সিআরগুলি লিখিতভাবে লিখিত লিখিত কোডগুলি দেখতে পাওয়া উচিত নয়।

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

যেমন,

// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{ 
    // This is *NOT* a CER
}
finally
{
    // This is a CER; guaranteed to run, if the try was entered, 
    // even if a StackOverflowException occurs.
}

দয়া করে নোট করুন যে এমনকি কোনও সিইআর কোনও এসওইয়ের ক্ষেত্রে চলবে না। আপনি এটি লেখার সময়, সিইআর তে এমএসডিএন ডকুমেন্টেশন ভুল / অসম্পূর্ণ ছিল। একটি এসওই FailFastঅভ্যন্তরীণভাবে ট্রিগার করবে । আমি সেগুলি ধরার একমাত্র উপায় হ'ল সিএলআর রানটাইম হোস্টিং কাস্টমাইজ করে । নোট করুন যে আপনার পয়েন্টটি এখনও কিছু অন্যান্য অ্যাসিনক্রোনাস ব্যতিক্রমগুলির জন্য বৈধ।
আবেল

10

এটির একটি খুব গুরুত্বপূর্ণ ব্যতিক্রম আছে যা আমি অন্য কোনও উত্তরে উল্লেখ করে দেখিনি এবং যা (18 বছরের জন্য সি # তে প্রোগ্রাম করার পরে) আমি বিশ্বাস করতে পারি না আমি জানি না।

যদি আপনি আপনার ব্লকের ভিতরে কোনও ধরণের ব্যতিক্রম ছোঁড়ে বা ট্রিগার করেন catch(কেবল অদ্ভুত StackOverflowExceptionsএবং সেই জাতীয় জিনিসগুলি নয় ) এবং আপনার try/catch/finallyঅন্য try/catchব্লকের মধ্যে পুরো ব্লক না থাকে তবে আপনার finallyব্লকটি কার্যকর হবে না। এটি সহজেই প্রদর্শিত হয় - এবং আমি যদি এটি নিজেই না দেখি, তবে আমি কতবার পড়েছি যে এটি কেবল সত্যই অদ্ভুত, ক্ষুদ্র কোণে-কেসগুলির ফলে finallyব্লক কার্যকর না করার কারণ হতে পারে, আমি এটি বিশ্বাস করি না।

static void Main(string[] args)
{
    Console.WriteLine("Beginning demo of how finally clause doesn't get executed");
    try
    {
        Console.WriteLine("Inside try but before exception.");
        throw new Exception("Exception #1");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Inside catch for the exception '{ex.Message}' (before throwing another exception).");
        throw;
    }
    finally
    {
        Console.WriteLine("This never gets executed, and that seems very, very wrong.");
    }

    Console.WriteLine("This never gets executed, but I wasn't expecting it to."); 
    Console.ReadLine();
}

আমি নিশ্চিত যে এর কোনও কারণ আছে তবে এটি উদ্ভট যে এটি আরও বেশি পরিচিত নয়। (এটি উদাহরণস্বরূপ এখানে উল্লেখ করা হয়েছে , তবে এই বিশেষ প্রশ্নের কোথাও নেই))


ঠিক আছে, finallyব্লকটি কেবল এই catchব্লকের জন্য ক্যাচ নয় ।
পিটার - মনিকা পুনরায়

7

আমি বুঝতে পারি আমি পার্টিতে দেরি করেছি তবে দৃশ্যে (ওপি-র উদাহরণ থেকে পৃথক) যেখানে এমএসডিএন বলছে আসলে একটি ব্যতিক্রম ছুঁড়ে ফেলা হয়েছে ( https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx ): "যদি ব্যতিক্রমটি ধরা না পড়ে তবে শেষ অবধি কার্যকর করা অপারেটিং সিস্টেম একটি ব্যতিক্রম আনওয়াইন্ড অপারেশন ট্রিগার করতে বেছে নেয় কিনা তার উপর নির্ভর করে।"

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


3

হ্যাঁ. এটি আসলে একটি শেষ অবধি মূল বক্তব্য। সিস্টেস্ট্রফিক কিছু না ঘটলে (মেমরির বাইরে, কম্পিউটার আনপ্লাগড না হওয়া ইত্যাদি) অবশেষে বিবৃতি সর্বদা কার্যকর করা উচিত।


1
আমি অসম্মতি জানাতে। Cf. আমার উত্তর. ট্রায়াল ব্লকের একটি সম্পূর্ণ স্বাভাবিক ব্যতিক্রম ব্লককে বাইপাস করার জন্য যথেষ্ট finallyযদি সেই ব্যতিক্রমটি কখনও ধরা না পড়ে। যে ধরা আমাকে আশ্চর্য ;-)।
পিটার - মনিকা পুনরায়

@ পিটারএ.স্নাইডার - এটি আকর্ষণীয়। অবশ্যই, এর প্রভাবগুলি আসলে খুব বেশি পরিবর্তন হয় না। যদি কল স্ট্যাকের কোনও কিছুই ব্যতিক্রমটি ধরতে চলেছে, তবে এর অর্থ হওয়া উচিত (যদি আমি সঠিকভাবে বুঝতে পারি) তবে প্রক্রিয়াটি সমাপ্ত হতে চলেছে। সুতরাং এটি পুলিং-দ্য প্লাগ পরিস্থিতির মতো। আমার ধারণা এই থেকে গ্রহণযোগ্যতাটি হ'ল আপনার সর্বদা একটি শীর্ষ-স্তরের বা অবরুদ্ধ ব্যতিক্রমী ক্যাচ থাকা উচিত।
জেফ্রি এল হুইলেটজ

হুবহু, আমি এটিই বুঝতে পারি। আমিও অবাক করেছিলাম। সত্য: সর্বাধিক সাধারণ সংস্থানগুলি স্বয়ংক্রিয়ভাবে প্রকাশিত হবে, বিশেষ মেমরির এবং খোলার ফাইলগুলিতে। তবে ওএসগুলি জানে না - উদাহরণ হিসাবে ওপেন সার্ভার বা ডাটাবেস সংযোগগুলি - দূরবর্তী দিক থেকে উন্মুক্ত থাকতে পারে কারণ সেগুলি কখনই সঠিকভাবে বন্ধ হয়নি; সকেটগুলি দীর্ঘায়িত হয়, ইত্যাদি ess আমার ধারণা, শীর্ষ স্তরের ব্যতিক্রম হ্যান্ডলারটি হ্যাঁ pr
পিটার - মনিকা পুনরায়


2

আপনি যদি System.exit (0) ব্যবহার করে অ্যাপ্লিকেশনটি থেকে বেরিয়ে আসছেন তবে অবশেষে চলবে না; হিসাবে হিসাবে

try
{
    System.out.println("try");
    System.exit(0);
}
finally
{
   System.out.println("finally");
}

ফলাফলটি ঠিক হবে: চেষ্টা করুন


4
আমি মনে করি আপনি ভুল ভাষায় উত্তর দিচ্ছেন, প্রশ্নটি ছিল c#তবে এটি মনে হচ্ছে Java। এবং এর বাইরেও বেশিরভাগ ক্ষেত্রেই System.exit()খারাপ ডিজাইনের ইঙ্গিত :-)
z00l

0

99% পরিস্থিতিতে এটির গ্যারান্টি দেওয়া হবে যে finallyব্লকের অভ্যন্তরে কোডটি চলবে, তবে এই দৃশ্যের কথাটি ভাবুন: আপনার কাছে একটি থ্রেড রয়েছে যার একটি try-> finallyব্লক (না catch) রয়েছে এবং আপনি সেই থ্রেডের মধ্যে একটি অবরুদ্ধ ব্যতিক্রম পেয়েছেন। এই ক্ষেত্রে, থ্রেডটি প্রস্থান করবে এবং এর finallyব্লকটি কার্যকর হবে না (অ্যাপ্লিকেশন এই ক্ষেত্রে চালিয়ে যেতে পারে)

এই দৃশ্যটি বেশ বিরল, তবে কেবল এটি দেখানোর জন্য যে উত্তরটি সবসময় "হ্যাঁ" নয়, এটি বেশিরভাগ সময় "হ্যাঁ" এবং কখনও কখনও বিরল অবস্থায় "না" হয় না।


0

অবশেষে ব্লকের মূল উদ্দেশ্য এর ভিতরে যা লেখা আছে তা সম্পাদন করা। এটি চেষ্টা বা ধরায় যা ঘটেছিল তার উপর নির্ভর করে না System সিস্টেমের সাথেই n

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