c# - কেন সি একটি ব্যতিক্রম ধরা এবং rethrow?




exception-handling try-catch (11)

আমি ধারা # সি-ডেটা ট্রান্সফার অবজেক্টটি সিরিয়ালাইজেবল ডিটিওগুলিতে দেখছি।

নিবন্ধ কোড এই টুকরা অন্তর্ভুক্ত:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

বাকি নিবন্ধটি বুদ্ধিমান এবং যুক্তিসঙ্গত (একটি নোব) দেখায়, কিন্তু যে চেষ্টা-ধরা-ছোঁয়াটি WTF এক্সক্সেশন ছুঁড়ে ফেলে ... এটি কি ব্যতিক্রমগুলির সাথে সামঞ্জস্যপূর্ণ নয়?

অতএব:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

অথবা আমি সি # এ ত্রুটি হ্যান্ডলিং সম্পর্কে কিছু মৌলিক অনুপস্থিত করছি? এটা বেশ জাভা হিসাবে একই (minus চেক ব্যতিক্রম), তাই না? ... যে, তারা উভয় সি ++ পরিমার্জিত।

স্ট্যাক ওভারফ্লো প্রশ্ন পুনরায় নিক্ষেপ পরামিতি-কম ধরা এবং কিছু করছেন না মধ্যে পার্থক্য? আমার মতামত সমর্থন করে বলে মনে হয় যে চেষ্টা-ধরা-ছোঁয়া-একটি নন-অপ।

সম্পাদনা করুন:

ভবিষ্যতে এই থ্রেড খুঁজে পেতে যে কেউ জন্য সংক্ষিপ্তভাবে শুধু ...

করো না

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

স্ট্যাক ট্রেস তথ্য সমস্যার মূল কারণ সনাক্ত করতে গুরুত্বপূর্ণ হতে পারে!

DO

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

কম নির্দিষ্ট বেশী (শুধুমাত্র জাভা মত) আগে আরো নির্দিষ্ট ব্যতিক্রম ধরা।

তথ্যসূত্র:


এই সব ঠিক ব্যতিক্রম হ্যান্ডলিং না ঠিক সমান?

ঠিক না, এটা একই নয়। এটি ব্যতিক্রম এর স্ট্যাকট্রাস পুনরায় সেট করে। যদিও আমি একমত যে এটি সম্ভবত একটি ভুল, এবং এভাবে খারাপ কোডের একটি উদাহরণ।


অন্যরা যা বলেছে তার পাশাপাশি, আমার সম্পর্কিত একটি প্রশ্নের সাথে উত্তরটি দেখুন যা দেখায় যে ধরা এবং পুনর্বহাল করা একটি নন-আপ নয় (এটি VB এর মধ্যে রয়েছে, তবে কোডের কিছুটি VB থেকে সীমাবদ্ধ করা যেতে পারে)।


আপনার প্রোগ্রামিং একটি লাইব্রেরি বা dll জন্য কাজ যখন এই দরকারী হতে পারে।

এই পুনরুদ্ধারের কাঠামোটি উদ্দেশ্যপূর্ণভাবে কল স্ট্যাকটি পুনরায় সেট করার জন্য ব্যবহার করা যেতে পারে যাতে ফাংশনের ভেতরে একটি পৃথক ফাংশন থেকে ব্যতিক্রমটি নিক্ষেপ করার পরিবর্তে আপনি ফাংশন থেকে ব্যতিক্রমটি পান।

আমি মনে করি এটি ব্যবহার করা হয় যাতে নিক্ষিপ্ত ব্যতিক্রমগুলি ক্লিনার হয় এবং লাইব্রেরির "শিকড়" তে না যায়।


আপনি প্রাক্তন নিক্ষেপ করতে চান না - এটি কল স্ট্যাক হারাবে। ব্যতিক্রম হ্যান্ডলিং (এমএসডিএন) দেখুন।

এবং হ্যাঁ, চেষ্টা করুন ... ধরা কিছুই দরকারী না (কল স্ট্যাক হারাতে ছাড়াও - এটি আসলে খারাপ - যদি না কিছু কারণে আপনি এই তথ্য প্রকাশ করতে চান না)।


এটা করো না,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

আপনি স্ট্যাক ট্রেস তথ্য হারাবেন ...

হয় না,

try { ... }
catch { throw; }

অথবা

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

উদাহরণস্বরূপ, আপনি যদি ব্যতিক্রমগুলি পরিচালনা করতে চান তবে এটির একটি কারণ হল আপনি যদি ব্যতিক্রমগুলি পরিচালনা করেন

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}

এটি ক্যাচ ব্লকের মধ্যে আপনি যা করছেন তা নির্ভর করে এবং আপনি যদি কোডিং কোডে ত্রুটিটি পাস করতে চান বা না চান।

আপনি Catch io.FileNotFoundExeption ex বলতে পারেন এবং তারপরে বিকল্প ফাইল পথ বা কিছু ব্যবহার করুন, তবে এখনও ত্রুটিটি নিক্ষেপ করুন।

এছাড়াও Throw Ex Throw পরিবর্তে Throw করছেন আপনি পুরো স্ট্যাক ট্রেস রাখতে পারবেন। পূর্বাবস্থায় ফিরুন বিবৃতি থেকে স্ট্যাক ট্রেস পুনরায় আরম্ভ করুন (আমি যে ইন্দ্রিয় তোলে আশা করি)।


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


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

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

সর্বাধিক .নেট ভাষায়, ব্যতিক্রমের ভিত্তিতে কোড গ্রহণের একমাত্র উপায় এটি catch হয় (যদিও এটি জানে যে এটি ব্যতিক্রমটি সমাধান করতে যাচ্ছে না), প্রশ্নটির ক্রিয়াটি সম্পাদন করুন এবং তারপরে পুনরায় throw )। অন্য কোন সম্ভাব্য পদ্ধতি যদি কোডটি কোনও ব্যতিক্রমের জন্য কোনও চিন্তা না করে তবে এটি একটি ভাল try/finally অবরুদ্ধ ব্লকের সাথে ok । ব্লকটির আগে ok , ok এবং ব্লকটি ছাড়ার আগে এবং ব্লকের অভ্যন্তরে যে কোনও return আগে ঠিক আছে। তারপর, finally , অনুমান করুন যে ok সেট না থাকলে, একটি ব্যতিক্রম ঘটেছে। যেমন একটি পদ্ধতি একটি catch / throw চেয়ে semantically ভাল, কিন্তু কুৎসিত এবং এটি হওয়া উচিত তুলনায় কম রক্ষণাবেক্ষণযোগ্য।


প্রথম; প্রবন্ধে কোডটি যেভাবে মন্দ তা করে। throw ex যেখানে এই ছোঁয়া বিবৃতি যেখানে বিন্দু ব্যতিক্রম কল ডাক স্ট্যাটাস পুনরায় সেট করা হবে; ব্যতিক্রমটি আসলে কোথায় তৈরি হয়েছিল সে সম্পর্কে তথ্য হারানো।

দ্বিতীয়ত, যদি আপনি এটির মতো ধরা এবং পুনরায় নিক্ষেপ করেন, তবে আমি কোনও যোগ মান দেখি না, উপরের কোড উদাহরণটি ঠিক যেমন ভাল হবে (অথবা, throw ex , এমনকি আরও ভালো) ততক্ষণ চেষ্টা না করেই।

যাইহোক, এমন কিছু ক্ষেত্রে যেখানে আপনি একটি ব্যতিক্রম ধরা এবং পুনঃস্থাপন করতে চাইতে পারেন। লগিং তাদের মধ্যে একজন হতে পারে:

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}

বেশিরভাগ উত্তর দৃশ্য-লগ-রিথ্রো সম্পর্কে কথা বলছে।

আপনার কোডে এটি লেখার পরিবর্তে AOP ব্যবহার করতে বিবেচনা করুন, বিশেষ করে Postsharp.Diagnostic.Toolkit সহ IncludeParameterValue এবং অন্তর্ভুক্ত করুনএকটি অক্ষর


সি # (সি # 6 এর আগে) সিআইএল "ফিল্টারেড ব্যতিক্রম" সমর্থন করে না, যা ভিবি করে, তাই সি # 1-5 এ একটি ব্যতিক্রম পুনঃনির্ধারণের একটি কারণ হল যে আপনার কাছে ক্যাচ হওয়ার সময় পর্যাপ্ত তথ্য নেই () আপনি আসলে ব্যতিক্রম ধরতে চেয়েছিলেন কিনা তা নির্ধারণ করতে।

উদাহরণস্বরূপ, ভিবি আপনি করতে পারেন

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... যা বিভিন্ন ErrorCode মানের সাথে MyExceptions পরিচালনা করবে না। V6 এর আগে C # তে, যদি আপনি ErrorCode 123 না হন তবে আপনাকে MyException ধরতে এবং পুনরায় নিক্ষেপ করতে হবে:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

সি # 6.0 থেকে আপনি VB এর মত ঠিক ফিল্টার করতে পারেন :

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}




try-catch