যদি একটি অবশেষে ব্লক একটি ব্যতিক্রম ছুঁড়ে, ঠিক কি ঘটে?
বিশেষত, ব্যতিক্রমটি শেষ অবধি মাঝখানে ফেলে দেওয়া হলে কী হয়। এই ব্লকের বাকী বিবৃতিগুলি (পরে) প্রার্থিত হবে?
আমি সচেতন যে ব্যতিক্রমগুলি উপরের দিকে প্রচার করবে।
যদি একটি অবশেষে ব্লক একটি ব্যতিক্রম ছুঁড়ে, ঠিক কি ঘটে?
বিশেষত, ব্যতিক্রমটি শেষ অবধি মাঝখানে ফেলে দেওয়া হলে কী হয়। এই ব্লকের বাকী বিবৃতিগুলি (পরে) প্রার্থিত হবে?
আমি সচেতন যে ব্যতিক্রমগুলি উপরের দিকে প্রচার করবে।
উত্তর:
একটি পরিশেষে ব্লক একটি ব্যতিক্রম কি ছোঁড়ার তাহলে ঠিক হবে?
এই ব্যতিক্রমটি বাইরে থেকে উপরে প্রচার করে এবং উচ্চ স্তরে পরিচালনা করা যাবে (যা)।
আপনার অবশেষে ব্লকটি যেখানে ব্যতিক্রম ছুঁড়েছে তার বাইরে শেষ হবে না ।
যদি পূর্বের ব্যতিক্রমটি পরিচালনা করার সময় শেষ অবধি ব্লকটি কার্যকর করা হয় তবে সেই প্রথম ব্যতিক্রমটি নষ্ট হয়ে যায়।
সি # 4 ভাষার স্পেসিফিকেশন: 8.9.5: অবশেষে ব্লক যদি অন্য একটি ব্যতিক্রম ছুঁড়ে দেয় তবে বর্তমান ব্যতিক্রম প্রক্রিয়াটি বন্ধ করা হবে।
ThreadAbortException
হলে পুরো অবশেষে ব্লকটি প্রথমে সমাপ্ত হবে, কারণ এটি একটি সমালোচনামূলক বিভাগ।
এই জাতীয় প্রশ্নের জন্য আমি ভিজ্যুয়াল স্টুডিওতে একটি খালি কনসোল অ্যাপ্লিকেশন প্রকল্পটি খোলার জন্য এবং একটি ছোট নমুনা প্রোগ্রাম লিখি:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
catch (Exception ex)
{
Console.WriteLine("Inner catch block handling {0}.", ex.Message);
throw;
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
আপনি যখন প্রোগ্রামটি চালাবেন আপনি সঠিক ক্রমটি দেখতে পাবেন যাতে কোনগুলি catch
এবং finally
ব্লকগুলি কার্যকর করা হয়। দয়া করে নোট করুন যে ব্যতিক্রমটি ছুঁড়ে দেওয়ার পরে অবশেষে ব্লকের কোডটি কার্যকর করা হবে না (বাস্তবে, এই নমুনা প্রোগ্রামটিতে ভিজ্যুয়াল স্টুডিও আপনাকে সতর্কও করবে যে এটি অ্যাক্সেসযোগ্য কোড সনাক্ত করেছে):
অভ্যন্তরীণ ক্যাচ ব্লক হ্যান্ডলিং ব্যতিক্রম চেষ্টা ব্লক থেকে ছোঁড়া। ইনার অবশেষে অবরুদ্ধ শেষ অবধি ব্লক থেকে বহিরাগত ক্যাচ ব্লক হ্যান্ডলিং ব্যতিক্রম। বাইরের অবশেষে অবরুদ্ধ
অতিরিক্ত মন্তব্য
মাইকেল দামাতভ যেমন উল্লেখ করেছেন, try
আপনি যদি কোনও (অভ্যন্তরীণ) catch
ব্লকে এটি পরিচালনা না করেন তবে ব্লকটি থেকে একটি ব্যতিক্রম "খাওয়া" হবে । আসলে, উপরের উদাহরণে পুনঃ নিক্ষেপ ব্যতিক্রম বাইরের ক্যাচ ব্লকে উপস্থিত হয় না does নীচে সামান্য পরিবর্তিত নমুনাটিকে আরও সুস্পষ্ট চেহারা হিসাবে দেখানোর জন্য:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
আউটপুট থেকে আপনি দেখতে পাচ্ছেন যে অভ্যন্তরীণ ব্যতিক্রমটি "হারানো" (অর্থাত্ উপেক্ষা করা):
ইনার অবশেষে অবরুদ্ধ শেষ অবধি ব্লক থেকে বহিরাগত ক্যাচ ব্লক হ্যান্ডলিং ব্যতিক্রম। বাইরের অবশেষে অবরুদ্ধ
finally
ব্লক (প্রায়শই) প্রায়শই কার্যকর করা হবে, এটি অভ্যন্তরীণ অবশেষে অবরুদ্ধ ব্লকের ক্ষেত্রেও রয়েছে (কেবল নমুনা প্রোগ্রামটি নিজে চেষ্টা করে দেখুন (একটি অবশেষে ব্লকটি পুনরুদ্ধারযোগ্য না হওয়ার ক্ষেত্রে কার্যকর করা হবে না) ব্যতিক্রম, যেমন একটি EngineExecutionException
, কিন্তু এই ধরনের একটি ক্ষেত্রে আপনার প্রোগ্রাম অবিলম্বে যাহাই হউক না কেন বন্ধ করে দেব)।
যদি কোনও ব্যতিক্রম মুলতুবি থাকে (যখন try
ব্লকের একটি finally
কিন্তু না থাকে catch
), নতুন ব্যতিক্রমটি এটিকে প্রতিস্থাপন করে।
যদি কোনও ব্যতিক্রম মুলতুবি না থাকে, তবে এটি finally
ব্লকের বাইরে কেবল একটি ব্যতিক্রম ছুঁড়ে মারার মতো কাজ করে ।
catch
ব্লক যে (পুনরায়) একটি ব্যতিক্রম ছোঁড়ার।
"আসল ব্যতিক্রম" ( try
অবরুদ্ধ নিক্ষেপ ) সংরক্ষণ এবং "শেষ অবধি" ত্যাগ করার জন্য দ্রুত (এবং বরং স্পষ্ট) স্নিপেট (এতে ছুঁড়েfinally
ব্লকের ), যদি মূলটি আপনার জন্য আরও গুরুত্বপূর্ণ হয়:
try
{
throw new Exception("Original Exception");
}
finally
{
try
{
throw new Exception("Finally Exception");
}
catch
{ }
}
উপরের কোডটি কার্যকর করা হলে, "আসল ব্যতিক্রম" কল স্ট্যাক প্রচার করে এবং "শেষ পর্যন্ত ব্যতিক্রম" হারিয়ে যায় "
একটি ব্যতিক্রমের কারণে কখনও খোলা হয়নি এমন স্ট্রিমটি বন্ধ করার চেষ্টা করার সময় ত্রুটি ধরার জন্য আমাকে এই কাজটি করতে হয়েছিল।
errorMessage = string.Empty;
try
{
byte[] requestBytes = System.Text.Encoding.ASCII.GetBytes(xmlFileContent);
webRequest = WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "text/xml;charset=utf-8";
webRequest.ContentLength = requestBytes.Length;
//send the request
using (var sw = webRequest.GetRequestStream())
{
sw.Write(requestBytes, 0, requestBytes.Length);
}
//get the response
webResponse = webRequest.GetResponse();
using (var sr = new StreamReader(webResponse.GetResponseStream()))
{
returnVal = sr.ReadToEnd();
sr.Close();
}
}
catch (Exception ex)
{
errorMessage = ex.ToString();
}
finally
{
try
{
if (webRequest.GetRequestStream() != null)
webRequest.GetRequestStream().Close();
if (webResponse.GetResponseStream() != null)
webResponse.GetResponseStream().Close();
}
catch (Exception exw)
{
errorMessage = exw.ToString();
}
}
যদি ওয়েব রিকুয়েস্ট তৈরি করা হয়েছিল তবে সেই সময়ে সংযোগ ত্রুটি ঘটেছে
using (var sw = webRequest.GetRequestStream())
এরপরে অবশেষে এমন একটি ব্যতিক্রম ধরা পড়বে যেগুলি মনে করে যে সংযোগগুলি উন্মুক্ত ছিল তা বন্ধ করে দেওয়ার চেষ্টা করেছিল কারণ ওয়েব রিকুইস্ট তৈরি হয়েছিল।
যদি শেষ অবধি ভিতরে চেষ্টা করে না থাকে তবে ওয়েব রিকোয়েস্ট সাফ করার সময় এই কোডটি অবিচ্ছিন্ন ব্যতিক্রম ঘটায়
if (webRequest.GetRequestStream() != null)
সেখান থেকে কোডটি ত্রুটিটি যথাযথভাবে পরিচালনা না করেই প্রস্থান করবে এবং সুতরাং কলিং পদ্ধতির জন্য সমস্যা তৈরি করে।
আশা করি এটি উদাহরণ হিসাবে সাহায্য করবে
অন্য ব্যতিক্রম সক্রিয় থাকাকালীন একটি ব্যতিক্রম ছোঁড়ার ফলে প্রথম ব্যতিক্রম দ্বিতীয় (পরে) ব্যতিক্রম দ্বারা প্রতিস্থাপিত হবে।
এখানে কিছু কোড রয়েছে যা চিত্রিত করে যা ঘটেছিল:
public static void Main(string[] args)
{
try
{
try
{
throw new Exception("first exception");
}
finally
{
//try
{
throw new Exception("second exception");
}
//catch (Exception)
{
//throw;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
কয়েক মাস আগেও আমি এরকম কিছু মুখোমুখি হয়েছি,
private void RaiseException(String errorMessage)
{
throw new Exception(errorMessage);
}
private void DoTaskForFinally()
{
RaiseException("Error for finally");
}
private void DoTaskForCatch()
{
RaiseException("Error for catch");
}
private void DoTaskForTry()
{
RaiseException("Error for try");
}
try
{
/*lacks the exception*/
DoTaskForTry();
}
catch (Exception exception)
{
/*lacks the exception*/
DoTaskForCatch();
}
finally
{
/*the result exception*/
DoTaskForFinally();
}
এ জাতীয় সমস্যা সমাধানের জন্য আমি একটি ইউটিলিটি ক্লাস তৈরি করেছি
class ProcessHandler : Exception
{
private enum ProcessType
{
Try,
Catch,
Finally,
}
private Boolean _hasException;
private Boolean _hasTryException;
private Boolean _hasCatchException;
private Boolean _hasFinnallyException;
public Boolean HasException { get { return _hasException; } }
public Boolean HasTryException { get { return _hasTryException; } }
public Boolean HasCatchException { get { return _hasCatchException; } }
public Boolean HasFinnallyException { get { return _hasFinnallyException; } }
public Dictionary<String, Exception> Exceptions { get; private set; }
public readonly Action TryAction;
public readonly Action CatchAction;
public readonly Action FinallyAction;
public ProcessHandler(Action tryAction = null, Action catchAction = null, Action finallyAction = null)
{
TryAction = tryAction;
CatchAction = catchAction;
FinallyAction = finallyAction;
_hasException = false;
_hasTryException = false;
_hasCatchException = false;
_hasFinnallyException = false;
Exceptions = new Dictionary<string, Exception>();
}
private void Invoke(Action action, ref Boolean isError, ProcessType processType)
{
try
{
action.Invoke();
}
catch (Exception exception)
{
_hasException = true;
isError = true;
Exceptions.Add(processType.ToString(), exception);
}
}
private void InvokeTryAction()
{
if (TryAction == null)
{
return;
}
Invoke(TryAction, ref _hasTryException, ProcessType.Try);
}
private void InvokeCatchAction()
{
if (CatchAction == null)
{
return;
}
Invoke(TryAction, ref _hasCatchException, ProcessType.Catch);
}
private void InvokeFinallyAction()
{
if (FinallyAction == null)
{
return;
}
Invoke(TryAction, ref _hasFinnallyException, ProcessType.Finally);
}
public void InvokeActions()
{
InvokeTryAction();
if (HasTryException)
{
InvokeCatchAction();
}
InvokeFinallyAction();
if (HasException)
{
throw this;
}
}
}
এবং এই মত ব্যবহৃত
try
{
ProcessHandler handler = new ProcessHandler(DoTaskForTry, DoTaskForCatch, DoTaskForFinally);
handler.InvokeActions();
}
catch (Exception exception)
{
var processError = exception as ProcessHandler;
/*this exception contains all exceptions*/
throw new Exception("Error to Process Actions", exception);
}
তবে আপনি যদি প্যারামিটারগুলি ব্যবহার করতে চান এবং প্রকারগুলি ফিরে যান তবে এটি অন্য গল্প
public void MyMethod()
{
try
{
}
catch{}
finally
{
CodeA
}
CodeB
}
কোডএ এবং কোডবি যেভাবে ব্যতিক্রম হয়েছে তা হ্যান্ডেল করা একই।
একটি finally
ব্লকে ফেলে দেওয়া ব্যতিক্রমের বিশেষ কিছু নেই, এটিকে কোড বি দ্বারা ব্যতিক্রম হিসাবে গণ্য করুন treat
ব্যতিক্রমটি প্রচার করে এবং একটি উচ্চ স্তরে পরিচালনা করা উচিত। যদি ব্যতিক্রমটি উচ্চ স্তরে পরিচালনা না করা হয় তবে অ্যাপ্লিকেশন ক্রাশ হয়ে যায়। "অবশেষে" ব্লক এক্সিকিউশনটি সেই স্থানে থামে যেখানে ব্যতিক্রম ছুঁড়ে দেওয়া হয়।
ব্যতিক্রম আছে কিনা তা নির্বিশেষে "অবশেষে" ব্লকটি কার্যকর করার গ্যারান্টিযুক্ত।
ট্রাই ব্লকে কোনও ব্যতিক্রম ঘটে যাওয়ার পরে যদি "অবশেষে" ব্লকটি কার্যকর করা হয়,
এবং যদি সেই ব্যতিক্রমটি পরিচালনা না করা হয়
এবং যদি শেষ অবধি ব্লকটি ব্যতিক্রম ছুঁড়ে
তারপরে ট্রাই ব্লকে যে ব্যতিক্রম ঘটেছিল তা হারিয়ে গেছে is
public class Exception
{
public static void Main()
{
try
{
SomeMethod();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static void SomeMethod()
{
try
{
// This exception will be lost
throw new Exception("Exception in try block");
}
finally
{
throw new Exception("Exception in finally block");
}
}
}