c# - একাধিক ব্যতিক্রম ক্যাচ একবার?




.net exception (18)

এটি কেবল System.Exception ধরা নিরুৎসাহিত করা হয়। পরিবর্তে, শুধুমাত্র "পরিচিত" ব্যতিক্রম ধরা উচিত।

এখন, এটি কখনও কখনও অনাক্রম্য পুনরাবৃত্তিমূলক কোড বাড়ে, উদাহরণস্বরূপ:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

আমি আশ্চর্য: উভয় ব্যতিক্রম ধরা এবং WebId = Guid.Empty কল শুধুমাত্র একটি উপায় আছে। একবার একবার কল কল?

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


সতর্ক এবং সতর্ক: এখনো অন্য ধরনের, কার্যকরী শৈলী।

লিঙ্কটি কী আপনার প্রশ্নের উত্তর সরাসরি দেয় না, তবে এটির মতো দেখতে প্রসারিত করা অসম্ভব:

static void Main() 
{ 
    Action body = () => { ...your code... };

    body.Catch<InvalidOperationException>() 
        .Catch<BadCodeException>() 
        .Catch<AnotherException>(ex => { ...handler... })(); 
}

(মূলত একটি ফাঁকা Catchওভারলোড সরবরাহ করে যা নিজেরাই প্রদান করে)

এই বড় প্রশ্ন কেন । আমি এখানে লাভ overweighs মনে হয় না :)


@Micheal

আপনার কোড সামান্য সংশোধিত সংস্করণ:

catch (Exception ex)
{
   Type exType = ex.GetType();
   if (exType == typeof(System.FormatException) || 
       exType == typeof(System.OverflowException)
   {
       WebId = Guid.Empty;
   } else {
      throw;
   }
}

স্ট্রিং তুলনা কুৎসিত এবং ধীর।


আপনি if catch স্কোপগুলির মধ্যে একটি বিবৃতি ব্যবহার করতে না চান if C# 6.0 আপনি Exception Filters সিনট্যাক্স ব্যবহার করতে পারেন যা প্রাকদর্শন সংস্করণগুলিতে সিএলআর দ্বারা ইতিমধ্যে সমর্থিত ছিল তবে VB.NET / MSIL বিদ্যমান ছিল:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
    WebId = Guid.Empty;
}

এই কোডটি কেবল তখনই InvalidDataException যখন এটি একটি InvalidDataException বা ArgumentNullException

প্রকৃতপক্ষে, আপনি মূলত যে কোন শর্তের ভিতরে যেটি বিভাগে রাখতে পারেন:

static int a = 8;

...

catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
    Console.WriteLine("Catch");
}

উল্লেখ্য যে catch সুযোগের মধ্যে if একটি বিবৃতির বিরোধিতা করা হয়, Exception Filters Exceptions নিক্ষেপ করতে পারে না এবং যখন তারা হয় বা যখন শর্তটি true হয় না তখন তার পরবর্তী catch অবস্থার পরিবর্তে মূল্যায়ন করা হবে:

static int a = 7;

static int b = 0;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

আউটপুট: সাধারণ ধরা।

যখন আরো বেশি হয় তখন এক true Exception Filter - প্রথমটি গ্রহণ করা হবে:

static int a = 8;

static int b = 4;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

আউটপুট: ক্যাচ।

এবং আপনি MSIL এ দেখতে if বিবৃতিটি if বিবৃতিতে অনুবাদ না করা হয় if Filters এবং Exceptions Filter 1 এবং Filter 2 সাথে চিহ্নিত এলাকার মধ্যে থেকে নিক্ষেপ করা যায় না তবে Exception নিক্ষেপকারী ফিল্টার পরিবর্তে ব্যর্থ হবে, শেষও endfilter কমান্ডটি ফিল্টারটির সাফল্যের / ব্যর্থতা নির্ধারণ করার আগে তুলনামূলক মানটি স্ট্যাকের দিকে ধাক্কা দেয় ( Catch 1 এক্সওআর Catch 2 অনুসারে কার্যকর হবে):

এছাড়াও, বিশেষত Guid Guid.TryParse পদ্ধতি আছে।


আপনি যদি C # 6 এ আপনার আবেদন আপগ্রেড করতে পারেন তবে আপনি ভাগ্যবান। নতুন সি # সংস্করণ এক্সপেশান ফিল্টার প্রয়োগ করেছে। সুতরাং আপনি এই লিখতে পারেন:

catch (Exception ex) when (ex is FormatException || ex is OverflowException) {
    WebId = Guid.Empty;
}

কিছু লোক মনে করে এই কোডটি একই

catch (Exception ex) {                
    if (ex is FormatException || ex is OverflowException) {
        WebId = Guid.Empty;
    }
    throw;
}

কিন্তু এটা না. প্রকৃতপক্ষে এটি সি # 6 এ একমাত্র নতুন বৈশিষ্ট্য যা আগের সংস্করণগুলিতে অনুকরণ করা সম্ভব নয়। প্রথমত, একটি পুনরায় ফরোয়ার্ড ধরা skipping তুলনায় আরো ওভারহেড মানে। দ্বিতীয়, এটি semantically সমতুল্য নয়। আপনি যখন আপনার কোড ডিবাগ করছেন তখন নতুন বৈশিষ্ট্য স্ট্যাকটি অক্ষত রাখে। এই বৈশিষ্ট্য ছাড়া ক্র্যাশ ডাম্প কম দরকারী বা এমনকি নিরর্থক।

roslyn.codeplex.com/discussions/541301 একটি roslyn.codeplex.com/discussions/541301 দেখুন। এবং একটি উদাহরণ পার্থক্য দেখাচ্ছে


কেমন

try
{
    WebId = Guid.Empty;
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
}
catch (OverflowException)
{
}

গ্রহনযোগ্য উত্তরটি গ্রহণযোগ্য বলে মনে হয়, কোড কোডিসিস / FxCop ব্যতীত এটি একটি সাধারণ ব্যতিক্রম টাইপ ধরার বিষয়টি সম্পর্কে অভিযোগ করবে।

এছাড়াও, এটি "হয়" অপারেটর সামান্য কর্মক্ষমতা হ্রাস হতে পারে বলে মনে হয়।

CA1800: অপ্রয়োজনীয়ভাবে "এর ফলাফল পরীক্ষা করার বিষয়ে বিবেচনা করুন" এর পরিবর্তে "অপারেটর হিসাবে" বলবেন না, তবে যদি আপনি এটি করেন তবে আপনি প্রতিটি ব্যতিক্রম আলাদাভাবে ধরার চেয়ে আরও কোড লিখতে পারবেন।

যাইহোক, এখানে আমি কি করবো:

bool exThrown = false;

try
{
    // Something
}
catch (FormatException) {
    exThrown = true;
}
catch (OverflowException) {
    exThrown = true;
}

if (exThrown)
{
    // Something else
}

ব্যতিক্রম ফিল্টার এখন সি # 6+ পাওয়া যায়। আপনি করতে পারেন

try
{
       WebId = new Guid(queryString["web"]);
}
catch (Exception ex) when(ex is FormatException || ex is OverflowException)
{
     WebId = Guid.Empty;
}

সম্পূর্ণতা অনুরোধের জন্য, .NET 4.0 থেকে কোডটি আবার লিখতে পারে:

Guid.TryParse(queryString["web"], out WebId);

TryParse ব্যতিক্রমগুলি TryParse না এবং ফরম্যাট ভুল হলে মিথ্যা ফেরত দেয়, ওয়েব আইডিকে Guid.Empty সেট করে।

C # 7 থেকে আপনি একটি পৃথক লাইনের উপর একটি পরিবর্তনশীল পরিচয় এড়াতে পারেন:

Guid.TryParse(queryString["web"], out Guid webId);

আপনি রিটার্নিং টুপলগুলি পার্স করার জন্যও পদ্ধতিগুলি তৈরি করতে পারেন, যা সংস্করণ 4.6 হিসাবে এখনও .NET ফ্রেমওয়ার্কে উপলব্ধ নয়:

(bool success, Guid result) TryParseGuid(string input) =>
    (Guid.TryParse(input, out Guid result), result);

এবং তাদের মত ব্যবহার করুন:

WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;

এই নিরর্থক উত্তরটির পরবর্তী নিরর্থক আপডেট আসে যখন আউট-প্যারামিটারগুলি নির্মান করা হয় # 12। :)


সি # 7 দিয়ে একটি সুইচ বিবৃতির পঠনযোগ্যতা রাখার সময় মাইকেল স্টুমের উত্তরটি উন্নত করা যেতে পারে:

catch (Exception ex)
{
    switch (ex)
    {
        case FormatException _:
        case OverflowException _:
            WebId = Guid.Empty;
            break;
        default:
            throw;
    }
}

জোসেফ ডাইগেলের উত্তরটি একটি ভাল সমাধান, তবে আমি নিম্নোক্ত কাঠামোটিকে একটু স্বল্প এবং কম ত্রুটিযুক্ত বলে মনে করি।

catch(Exception ex)
{   
    if (!(ex is SomeException || ex is OtherException)) throw;

    // Handle exception
}

অভিব্যক্তি inverting কয়েক সুবিধার আছে:

  • একটি রিটার্ন বিবৃতি প্রয়োজন হয় না
  • কোড নেস্টেড হয় না
  • জোসেফের সমাধানটি প্রকাশের থেকে আলাদা হয়ে যাওয়া 'থ্রো' বা 'রিটার্ন' বিবৃতি ভুলে যাওয়ার কোন ঝুঁকি নেই।

এটি এমনকি একটি লাইন কম্প্যাক্ট করা যেতে পারে (যদিও খুব সুন্দর নয়)

catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;

    // Handle exception
}

সম্পাদনা: সি # 6.0 এ ব্যতিক্রম ফিল্টারিং সিনট্যাক্সটিকে একটু ক্লিনার করে এবং কোনও বর্তমান সমাধান ছাড়াই অন্যান্য অনেকগুলি সুবিধা নিয়ে আসে। (সবচেয়ে উল্লেখযোগ্যভাবে স্ট্যাক unharmed রেখে)

সি # 6.0 সিনট্যাক্স ব্যবহার করে একই সমস্যাটি কীভাবে দেখবে এখানে:

catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
    // Handle exception
}

সম্পাদন করুন: আমি অন্যদের সাথে একমত, যারা সি # 6.0 হিসাবে, ব্যতিক্রম ফিল্টারগুলি এখন যেতে পুরোপুরি দুর্দান্ত উপায়: catch (Exception ex) when (ex is ... || ex is ... )

যেহেতু আমি এখনও এক-লং-লাইন লেআউটের ঘৃণা করি এবং ব্যক্তিগতভাবে কোডটি নিচের মতোই রাখব। আমি এটা নান্দনিক হিসাবে কার্যকরী মনে হয়, আমি বিশ্বাস করি এটা বোঝার উন্নতি। কিছু অসম্মত হতে পারে:

catch (Exception ex) when (
    ex is ...
    || ex is ...
    || ex is ...
)

মূল:

আমি জানি, আমি পার্টিতে একটু দেরিতে আছি, কিন্তু পবিত্র ধোঁয়া ...

সরাসরি পশ্চাদ্ধাবন করা, এই ধরনের পূর্বের উত্তরটিকে সদৃশ করে তুলবে তবে যদি আপনি সত্যিই ব্যতিক্রমগুলির জন্য একটি সাধারণ পদক্ষেপ সঞ্চালন করতে চান এবং পুরো পদ্ধতিটিকে এক পদ্ধতির মধ্যে সুষ্ঠু এবং পরিচ্ছন্ন রাখতে চান তবে কেন কেবল একটি ল্যাম্বা ব্যবহার করবেন না / বন্ধ / ইনলাইন ফাংশন নিম্নলিখিত মত কিছু করতে? আমি বলতে চাচ্ছি, সম্ভাবনাগুলি খুব ভাল যে আপনি উপলব্ধি করতে পারবেন যে আপনি কেবল সেই ক্লোজারটি একটি পৃথক পদ্ধতি তৈরি করতে চান যা আপনি সর্বত্র ব্যবহার করতে পারেন। কিন্তু তারপর এটি structurally বাকি কোড পরিবর্তন ছাড়া যে সহজ কাজ করতে সহজ হবে। রাইট?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
    {
        // try some stuff
    }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

আমি অবাক হব না কিন্তু সতর্কতা অবলম্বন করতে পারি ( সতর্কতা: একটু বিরক্তিকর / বিরক্তিকর) কেন পৃথিবীতে এই সমস্ত প্রচেষ্টায় মূলত কেবল নীচের প্রতিস্থাপন করতে হয়:

try
{
    // try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

... এই পরবর্তী কোডের গন্ধের কিছু পাগলের পার্থক্যের সাথে, আমি উদাহরণস্বরূপ, শুধুমাত্র কয়েকটি কীস্ট্রোক সংরক্ষণ করার জন্য জাহির করা।

// sorta sucks, let's be honest...
try
{
    // try some stuff
}
catch( Exception ex )
{
    if (ex is FormatException ||
        ex is OverflowException ||
        ex is ArgumentNullException)
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

এটি অবশ্যই স্বয়ংক্রিয়ভাবে আরো পাঠযোগ্য নয় কারণ।

অনুমিত, আমি তিনটি অভিন্ন উদাহরণ /* write to a log, whatever... */ return; প্রথম উদাহরণ আউট।

কিন্তু যে আমার বিন্দু সাজানোর। আপনি সব ফাংশন / পদ্ধতি শুনেছেন, অধিকার? সিরিয়াসলি। একটি সাধারণ ErrorHandler ফাংশন লিখুন এবং, যেমন, এটি প্রতিটি ধরা ব্লক থেকে কল করুন।

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

রক্ষণাবেক্ষণের ফেজ, যারা প্রোগ্রামিংয়ের তুলনায় অপেক্ষাকৃত নতুন, তাদের প্রকল্পটির মোট জীবদ্দশায় 98.7% বা তার বেশি যোগদান করতে যাচ্ছে, এবং দরিদ্র schmuck রক্ষণাবেক্ষণকারীরা অবশ্যই আপনার চেয়ে অন্য কেউ হতে যাচ্ছে। এবং খুব ভাল সুযোগ তারা আপনার নাম cursing কাজের 50% সময় ব্যয় হবে।

এবং অবশ্যই FxCop আপনার উপর ছিটিয়ে দেয় এবং তাই আপনাকে আপনার কোডটিতে এমন একটি বৈশিষ্ট্য যুক্ত করতে হবে যা চলমান প্রোগ্রামের সাথে ঠিকভাবে জিপ করতে পারে এবং শুধুমাত্র FxCop কে কোন সমস্যাটি উপেক্ষা করতে বলবে 99.9% ক্ষেত্রে এটি পুরোপুরি সম্পূর্ণ flagging সঠিক। এবং, দুঃখিত, আমি ভুল হতে পারে, কিন্তু যে "উপেক্ষা" বৈশিষ্ট্য আসলে আপনার অ্যাপ্লিকেশন মধ্যে সংকলিত আপ শেষ?

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

যখন আপনি আরও তিনটি ব্যতিক্রম ধরন, একটি মাস বা দুইটি এখন যোগ করেন তখন এটি কত কম পাঠযোগ্য? (উত্তর: এটা অনেক কম পঠনযোগ্য পায়)।

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

এমনি বলছি...

// super sucks...
catch( Exception ex )
{
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

এটি একটি ক্লাসিক সমস্যা প্রতিটি সি # বিকাশকারী অবশেষে মুখ।

আমাকে 2 টি প্রশ্নের মধ্যে আপনার প্রশ্ন বিরতি দিন। প্রথম,

আমি একযোগে একাধিক ব্যতিক্রম ধরতে পারি?

সংক্ষেপে, না।

যা পরের প্রশ্ন বাড়ে,

আমি একই ক্যাচ () ব্লকটিতে একাধিক ব্যতিক্রম প্রকারগুলি ধরতে পারি না এমন প্রদত্ত ডুপ্লিকেট কোডটি কীভাবে এড়াতে পারি?

আপনার নির্দিষ্ট নমুনাটি দেওয়া হয়েছে, যেখানে ফোল-ব্যাক মান নির্মাণের জন্য সস্তা, আমি এই পদক্ষেপগুলি অনুসরণ করতে পছন্দ করি:

  1. পতনশীল মান ওয়েবাইড শুরু করুন।
  2. একটি অস্থায়ী পরিবর্তনশীল একটি নতুন গুইড গঠন।
  3. সম্পূর্ণরূপে নির্মিত অস্থায়ী পরিবর্তনশীল ওয়েবআইডি সেট করুন। এই {{ব্লক} চেষ্টা করে চূড়ান্ত বিবৃতিটি তৈরি করুন।

সুতরাং কোডটি দেখায়:

try
{
    WebId = Guid.Empty;
    Guid newGuid = new Guid(queryString["web"]);
    // More initialization code goes here like 
    // newGuid.x = y;
    WebId = newGuid;
}
catch (FormatException) {}
catch (OverflowException) {}

যদি কোন ব্যতিক্রম নিক্ষেপ করা হয়, তবে WebId অর্ধ-নির্মিত মানের সেট করা হয় না, এবং Guid.Empty থাকে।

ফোল-ব্যাক মান নির্মাণ করা যদি ব্যয়বহুল হয় এবং একটি মান পুনরায় সেট করা খুব সস্তা হয়, তবে আমি রিসেট কোডটিকে তার নিজের ফাংশনে স্থানান্তরিত করব:

try
{
    WebId = new Guid(queryString["web"]);
    // More initialization code goes here.
}
catch (FormatException) {
    Reset(WebId);
}
catch (OverflowException) {
    Reset(WebId);
}

শুধু চেষ্টা করুন এবং দুই বার ধরা।

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
try
{
    WebId = new Guid(queryString["web"]);
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

ইহা খুবই সাধারন!!


সি # 6.0-এ ব্যতিক্রম ব্যতিক্রমগুলি ব্যতিক্রম হ্যান্ডলিংয়ের উন্নতি

try
{
    DoSomeHttpRequest();
}
catch (System.Web.HttpException e)
{
    switch (e.GetHttpCode())
    {
        case 400:
            WriteLine("Bad Request");
        case 500:
            WriteLine("Internal Server Error");
        default:
            WriteLine("Generic Error");
    }
}

2015-12-15 আপডেট করুন: সি # 6 এর জন্য https://.com/a/22864936/1718702 দেখুন । এটি একটি ক্লিনার এবং এখন ভাষার মধ্যে মান।

একবার ধরতে এবং ব্যতিক্রমগুলি ফিল্টার করার জন্য আরো মার্জিত সমাধান চান এমন লোকেদের জন্য গিয়ার করা , আমি নীচে প্রদর্শিত হিসাবে একটি এক্সটেনশান পদ্ধতি ব্যবহার করি।

আমার লাইব্রেরিতে এই এক্সটেনশানটি ইতিমধ্যেই ছিল, মূলত অন্যান্য উদ্দেশ্যে লিখিত ছিল, তবে typeব্যতিক্রমগুলি পরীক্ষা করার জন্য এটি পুরোপুরি পুরোপুরি কাজ করেছিল । প্লাস, আমিও, এটা ||বিবৃতি একটি গুচ্ছ চেয়ে ক্লিনার দেখায় । এছাড়াও, গৃহীত উত্তরগুলির বিপরীতে, আমি স্পষ্ট ব্যতিক্রম হ্যান্ডলিং পছন্দ করি যাতে ex is ...অযৌক্তিক আচরণের কারণে বঞ্চিত শ্রেণীগুলি পিতামাতার প্রকারের জন্য নির্ধারিত হয়)।

ব্যবহার

if (ex.GetType().IsAnyOf(
    typeof(FormatException),
    typeof(ArgumentException)))
{
    // Handle
}
else
    throw;

IsAnyOf.cs এক্সটেনশান (নির্ভরশীলতা জন্য উদাহরণ হ্যান্ডলিং সম্পূর্ণ ত্রুটি দেখুন)

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter matches at least one of the passed in comparisons.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_comparisons">Values to compare against.</param>
        /// <returns>True if a match is found.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
        {
            // Validate
            p_parameter
                .CannotBeNull("p_parameter");
            p_comparisons
                .CannotBeNullOrEmpty("p_comparisons");

            // Test for any match
            foreach (var item in p_comparisons)
                if (p_parameter.Equals(item))
                    return true;

            // Return no matches found
            return false;
        }
    }
}

সম্পূর্ণ ত্রুটি হ্যান্ডলিং উদাহরণ (নতুন কনসোল অ্যাপ্লিকেশন অন কপি-পেস্ট)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.FluentValidation;

namespace IsAnyOfExceptionHandlerSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // High Level Error Handler (Log and Crash App)
            try
            {
                Foo();
            }
            catch (OutOfMemoryException ex)
            {
                Console.WriteLine("FATAL ERROR! System Crashing. " + ex.Message);
                Console.ReadKey();
            }
        }

        static void Foo()
        {
            // Init
            List<Action<string>> TestActions = new List<Action<string>>()
            {
                (key) => { throw new FormatException(); },
                (key) => { throw new ArgumentException(); },
                (key) => { throw new KeyNotFoundException();},
                (key) => { throw new OutOfMemoryException(); },
            };

            // Run
            foreach (var FooAction in TestActions)
            {
                // Mid-Level Error Handler (Appends Data for Log)
                try
                {
                    // Init
                    var SomeKeyPassedToFoo = "FooParam";

                    // Low-Level Handler (Handle/Log and Keep going)
                    try
                    {
                        FooAction(SomeKeyPassedToFoo);
                    }
                    catch (Exception ex)
                    {
                        if (ex.GetType().IsAnyOf(
                            typeof(FormatException),
                            typeof(ArgumentException)))
                        {
                            // Handle
                            Console.WriteLine("ex was {0}", ex.GetType().Name);
                            Console.ReadKey();
                        }
                        else
                        {
                            // Add some Debug info
                            ex.Data.Add("SomeKeyPassedToFoo", SomeKeyPassedToFoo.ToString());
                            throw;
                        }
                    }
                }
                catch (KeyNotFoundException ex)
                {
                    // Handle differently
                    Console.WriteLine(ex.Message);

                    int Count = 0;
                    if (!Validate.IsAnyNull(ex, ex.Data, ex.Data.Keys))
                        foreach (var Key in ex.Data.Keys)
                            Console.WriteLine(
                                "[{0}][\"{1}\" = {2}]",
                                Count, Key, ex.Data[Key]);

                    Console.ReadKey();
                }
            }
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter matches at least one of the passed in comparisons.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_comparisons">Values to compare against.</param>
        /// <returns>True if a match is found.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
        {
            // Validate
            p_parameter
                .CannotBeNull("p_parameter");
            p_comparisons
                .CannotBeNullOrEmpty("p_comparisons");

            // Test for any match
            foreach (var item in p_comparisons)
                if (p_parameter.Equals(item))
                    return true;

            // Return no matches found
            return false;
        }

        /// <summary>
        /// Validates if any passed in parameter is equal to null.
        /// </summary>
        /// <param name="p_parameters">Parameters to test for Null.</param>
        /// <returns>True if one or more parameters are null.</returns>
        public static bool IsAnyNull(params object[] p_parameters)
        {
            p_parameters
                .CannotBeNullOrEmpty("p_parameters");

            foreach (var item in p_parameters)
                if (item == null)
                    return true;

            return false;
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter is not null, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void CannotBeNull(this object p_parameter, string p_name)
        {
            if (p_parameter == null)
                throw
                    new
                        ArgumentNullException(
                        string.Format("Parameter \"{0}\" cannot be null.",
                        p_name), default(Exception));
        }
    }
}

namespace Common.FluentValidation
{
    public static partial class Validate
    {
        /// <summary>
        /// Validates the passed in parameter is not null or an empty collection, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static void CannotBeNullOrEmpty<T>(this ICollection<T> p_parameter, string p_name)
        {
            if (p_parameter == null)
                throw new ArgumentNullException("Collection cannot be null.\r\nParameter_Name: " + p_name, default(Exception));

            if (p_parameter.Count <= 0)
                throw new ArgumentOutOfRangeException("Collection cannot be empty.\r\nParameter_Name: " + p_name, default(Exception));
        }

        /// <summary>
        /// Validates the passed in parameter is not null or empty, throwing a detailed exception message if the test fails.
        /// </summary>
        /// <param name="p_parameter">Parameter to validate.</param>
        /// <param name="p_name">Name of tested parameter to assist with debugging.</param>
        /// <exception cref="ArgumentException"></exception>
        public static void CannotBeNullOrEmpty(this string p_parameter, string p_name)
        {
            if (string.IsNullOrEmpty(p_parameter))
                throw new ArgumentException("String cannot be null or empty.\r\nParameter_Name: " + p_name, default(Exception));
        }
    }
}

দুই নমুনা ইউনিট ইউনিট টেস্ট

Exceptionধরনগুলির জন্য মিলিং আচরণ সঠিক (অর্থাত্ একটি শিশু তার কোনও মূল প্রকারের জন্য মেলে না)।

using System;
using System.Collections.Generic;
using Common.FluentValidation;
using NUnit.Framework;

namespace UnitTests.Common.Fluent_Validations
{
    [TestFixture]
    public class IsAnyOf_Tests
    {
        [Test, ExpectedException(typeof(ArgumentNullException))]
        public void IsAnyOf_ArgumentNullException_ShouldNotMatch_ArgumentException_Test()
        {
            Action TestMethod = () => { throw new ArgumentNullException(); };

            try
            {
                TestMethod();
            }
            catch (Exception ex)
            {
                if (ex.GetType().IsAnyOf(
                    typeof(ArgumentException), /*Note: ArgumentNullException derrived from ArgumentException*/
                    typeof(FormatException),
                    typeof(KeyNotFoundException)))
                {
                    // Handle expected Exceptions
                    return;
                }

                //else throw original
                throw;
            }
        }

        [Test, ExpectedException(typeof(OutOfMemoryException))]
        public void IsAnyOf_OutOfMemoryException_ShouldMatch_OutOfMemoryException_Test()
        {
            Action TestMethod = () => { throw new OutOfMemoryException(); };

            try
            {
                TestMethod();
            }
            catch (Exception ex)
            {
                if (ex.GetType().IsAnyOf(
                    typeof(OutOfMemoryException),
                    typeof(Exception)))
                    throw;

                /*else... Handle other exception types, typically by logging to file*/
            }
        }
    }
}

এই ইতিমধ্যে দীর্ঘ থ্রেড আমার সংক্ষিপ্ত উত্তর যোগ করতে চেয়েছিলেন। এমন কিছু যা উল্লেখ করা হয়নি তা হল ধরা বিবৃতির অগ্রাধিকারের ক্রম, বিশেষ করে আপনাকে ধরার চেষ্টা করা প্রতিটি ব্যতিক্রমের সুযোগ সম্পর্কে সচেতন থাকা দরকার।

উদাহরণস্বরূপ, যদি আপনি একটি "সকল-ক্যাচ" ব্যতিক্রম ব্যবহার ব্যতিক্রম এটি অন্যান্য সব ধরা বিবৃতি preceed হবে এবং আপনি সম্ভবত কম্পাইলার এরর তবে পাবেন যদি আপনি আপনি শৃঙ্খল আপ আপনার ধরা বিবৃতি (বিরোধী প্যাটার্ন আমি মনে করি বিট করতে পারেন বিপরীত ) আপনি নীচের ক্যাচ-এ সমস্ত ব্যতিক্রম টাইপটি রাখতে পারেন এবং এটি এমন কোনও ব্যতিক্রমকে ধরে রাখবে যা আপনার প্রচেষ্টায় উচ্চতরভাবে পূরণ না করে .. ক্যাচ ব্লক:

            try
            {
                // do some work here
            }
            catch (WebException ex)
            {
                // catch a web excpetion
            }
            catch (ArgumentException ex)
            {
                // do some stuff
            }
            catch (Exception ex)
            {
                // you should really surface your errors but this is for example only
                throw new Exception("An error occurred: " + ex.Message);
            }

আমি অত্যন্ত এই MSDN নথির পর্যালোচনা লোকেরা সুপারিশ:

ব্যতিক্রম আধিপত্য


সুতরাং আপনি প্রতিটি ব্যতিক্রম সুইচ মধ্যে কোড প্রচুর পুনরাবৃত্তি করছি? একটি পদ্ধতি নিষ্কাশনের মত শব্দ ঈশ্বরের ধারণা হতে পারে, তাই না?

তাই আপনার কোড এই নিচে আসে:

MyClass instance;
try { instance = ... }
catch(Exception1 e) { Reset(instance); }
catch(Exception2 e) { Reset(instance); }
catch(Exception) { throw; }

void Reset(MyClass instance) { /* reset the state of the instance */ }

আমি আশ্চর্য যে কোন এক কোড-সদৃশ লক্ষ্য।

সি # 6 থেকে আপনি ইতিমধ্যে exception-filters হিসাবে exception-filters আছে ইতিমধ্যে অন্যদের দ্বারা উল্লিখিত। সুতরাং আপনি উপরের কোডটি সংশোধন করতে পারেন:

try { ... }
catch(Exception e) when(e is Exception1 || e is Exception2)
{ 
    Reset(instance); 
}

catch (Exception ex)
{
    if (!(
        ex is FormatException ||
        ex is OverflowException))
    {
        throw;
    }
    Console.WriteLine("Hello");
}




exception-handling