একবারে একাধিক ব্যতিক্রম ধরা?


2140

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

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

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

আমি অবাক: উভয় ব্যতিক্রম ধরা এবং কেবল WebId = Guid.Emptyএকবার কল করার জন্য কি কোনও উপায় আছে ?

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


5
আপনি ব্যবহার করে থাকেন .net 4 এবং উপরে আমি ব্যবহার করতে পছন্দ aggregateexception msdn.microsoft.com/en-us/library/system.aggregateexception.aspx
Bepenfriends

2
Bepenfriends- যেহেতু System.Guid নিক্ষেপ না AggregateException , যদি আপনি (অথবা) দেখাচ্ছে কিভাবে আপনি একটি AggregateException ইত্যাদি .. সেটিকে মোড়ানো হবে একটি উত্তর পোস্ট করতে মহান হতে হবে
ওয়ার


11
"এটি কেবল সিস্টেমকে ধরতে নিরুৎসাহিত করা হয়েছে x -আর যদি পদ্ধতিটি 32 ধরণের ব্যতিক্রম ছুঁড়ে ফেলতে পারে তবে কেউ কী করবে? তাদের প্রত্যেকের জন্য আলাদা আলাদা করে লেখেন?
জিওরজিম

5
যদি কোনও পদ্ধতির 32 টি বিভিন্ন ধরণের ব্যতিক্রম ছোঁড়া হয় তবে এটি খারাপভাবে লেখা। এটি হয় নিজস্ব কলগুলি ব্যতিক্রমগুলি ধরছে না, এটি একটি পদ্ধতিতে খুব বেশি কাজ করছে, বা 32 32 এর সমস্ত সংখ্যাগরিষ্ঠ কোনও কারণ কারণ সহ একক ব্যতিক্রম হওয়া উচিত।
ফ্লাইনে 1179

উত্তর:


2100

টাইপগুলি ধরুন System.Exceptionএবং স্যুইচ করুন

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

    throw;
}

69
দুর্ভাগ্যক্রমে, FxCop (যেমন - ভিজ্যুয়াল স্টুডিও কোড বিশ্লেষণ) আপনি যখন ব্যতিক্রমটি ধরেন তখন পছন্দ করে না।
অ্যান্ড্রু গ্যারিসন

15
আমি ব্যতিক্রম ধরা না দেওয়ার সাথে একমত, তবে, এই ক্ষেত্রে, ক্যাচটি একটি ফিল্টার। আপনার কাছে একটি স্তর উচ্চতর থাকতে পারে যা অন্যান্য ব্যতিক্রম প্রকারগুলি পরিচালনা করবে। আমি এটি সঠিক বলব, যদিও এটিতে একটি ক্যাচ (ব্যতিক্রম x) অন্তর্ভুক্ত রয়েছে। এটি প্রোগ্রামের প্রবাহকে পরিবর্তন করে না, এটি কেবলমাত্র কিছু ব্যাতিকাল পরিচালনা করে তারপরে বাকি অ্যাপ্লিকেশনটিকে অন্য কোনও ব্যতিক্রম প্রকারের সাথে চুক্তি করে।
lkg

28
উপরের কোডটি ব্যবহার করা হলে FxCop এর সর্বশেষতম সংস্করণ একটি ব্যতিক্রম ছুঁড়ে না।
পিটার

28
প্রথমে অপের কোডটিতে কী ছিল তা নিশ্চিত নয়। # 1 গৃহীত উত্তরটি প্রায় অনেক দ্বিগুণ লাইন এবং কম পাঠযোগ্য able
জোয়াও Bragança এর

22
@ জোওবাগ্রাগানিয়া: এই উদাহরণটিতে এই উত্তরটি আরও লাইন ব্যবহার করার সময়, আপনি উদাহরণস্বরূপ ফাইল আইও নিয়ে কাজ করছেন কিনা তা কল্পনা করার চেষ্টা করুন এবং আপনি যা করতে চান সেগুলি ব্যতিক্রমগুলি ধরা এবং কিছু লগ বার্তাপ্রেরণ করা, তবে কেবল আপনিই আশা করেন যে আপনি আপনার কাছ থেকে এসেছেন ফাইল IO পদ্ধতি। তারপরে আপনাকে প্রায়শই একটি বৃহত সংখ্যার (প্রায় 5 বা তার বেশি) বিভিন্ন ধরণের ব্যতিক্রম নিয়ে কাজ করতে হয়। এই পরিস্থিতিতে, এই পদ্ধতির আপনাকে কিছু লাইন সংরক্ষণ করতে পারে।
Xilconic

593

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

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

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

মূল:

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

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

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এবং isকীওয়ার্ড সহ) উভয়ই উল্লেখযোগ্যভাবে কম পঠনযোগ্য এবং একই সাথে আপনার প্রকল্পের রক্ষণাবেক্ষণের পর্যায়ে আরও ত্রুটি-ঝুঁকির প্রবণতা রয়েছে।

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

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

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

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

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

এমনি বলছি...

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

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

8
একটি ত্রুটি হ্যান্ডলিং ফাংশন ব্যবহার করা কাজ করবে না যদি আপনি এটিকে অন্তর্ভুক্ত করতে চান throw;। প্রতিটি ক্যাচ ব্লকে আপনাকে কোডটির সেই লাইনটি পুনরাবৃত্তি করতে হবে (স্পষ্টতই বিশ্বের শেষ নয় তবে উল্লেখ করার মতো এটি কোড যা পুনরাবৃত্তি করা দরকার)।
kad81

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

2
হাই @ রিটফ্যাঙ্ক, কেবল Func<Exception, MyEnumType>পরিবর্তে ব্যবহার করুন Action<Exception>। এটা Func<T, Result>সঙ্গে, Resultরিটার্ন টাইপ হচ্ছে।
ক্রেগ

3
আমি এখানে সম্পূর্ণ চুক্তিতে আছি। আমিও প্রথম উত্তরটি পড়েছি এবং চিন্তাকে যৌক্তিক বলে মনে হয়। সমস্ত ব্যতিক্রম হ্যান্ডলারের জন্য জেনেরিক 1 এ সরানো হয়েছে। আমার ভিতরে থাকা কিছু আমাকে অভ্যন্তরীণভাবে ছাঁটাই করেছে ... তাই আমি কোডটি উল্টে দিয়েছি। তারপরে এই সৌন্দর্য জুড়ে এসেছিল! এই প্রয়োজন গৃহীত উত্তর হতে
কোনোর গালাঘের

372

অন্যরা যেমন উল্লেখ করেছে, ifকী চলছে তা নির্ধারণ করতে আপনার ক্যাচ ব্লকের ভিতরে একটি বিবৃতি থাকতে পারে। সি # 6 ব্যতিক্রম ফিল্টারগুলি সমর্থন করে, তাই নিম্নলিখিতগুলি কাজ করবে:

try {  }
catch (Exception e) when (MyFilter(e))
{
    
}

MyFilterপদ্ধতি তারপর ভালো কিছু চেহারা পারে:

private bool MyFilter(Exception e)
{
  return e is ArgumentNullException || e is FormatException;
}

বিকল্পভাবে, এগুলি সমস্ত ইনলাইন করা যায় (যখন বিবৃতিটির ডান হাতের বিবরণটি কেবল বুলিয়ান এক্সপ্রেশন হতে পারে)।

try {  }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    
}

এটি ব্লকের ifমধ্যে থেকে একটি বিবৃতি ব্যবহারের চেয়ে পৃথক catch, ব্যতিক্রম ফিল্টারগুলি স্ট্যাকটি উন্মুক্ত করবে না

এটি পরীক্ষা করে দেখতে আপনি ভিজ্যুয়াল স্টুডিও 2015 ডাউনলোড করতে পারেন ।

আপনি যদি ভিজ্যুয়াল স্টুডিও 2013 ব্যবহার চালিয়ে যেতে চান তবে নীচের নুগেট প্যাকেজটি ইনস্টল করতে পারেন:

ইনস্টল-প্যাকেজ মাইক্রোসফট. নেট.কম্পেলার্স

লেখার সময়, এটি সি # 6 এর জন্য সমর্থন অন্তর্ভুক্ত করবে।

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


3
ধৈর্য সহকারে 6 এর সরকারী মুক্তির অপেক্ষায় ... আমি যখন দেখতে পেলাম তখন এটি চেক করা দেখতে চাই।
রাবারডাক

@ রাবারডাক আমি সি # from থেকে নাল প্রচারের জন্য অপারেটরটির জন্য মরে যাচ্ছি my বিশাল প্রভাব সহ ছোট ছোট অনেক উন্নতি। উত্তর হিসাবে চিহ্নিত হওয়ার জন্য, গুরুত্বপূর্ণ নয়, যতক্ষণ না লোকে এই ইচ্ছাটি / সম্ভব বুঝতে পারে ততক্ষণ আমি খুশি I'm
জো

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

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

188

দুর্ভাগ্যক্রমে সি # তে নয়, এটি করার জন্য আপনার যেমন একটি ব্যতিক্রম ফিল্টার প্রয়োজন এবং সি # এমএসআইএল-র বৈশিষ্ট্যটি প্রকাশ করে না। ভিবি.এনইটি-তে যদিও এই ক্ষমতা রয়েছে, যেমন

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

আপনি যা করতে পারেন তা হ'ল আপনার অন-ত্রুটি কোডটি encapsulate করতে একটি বেনামি ফাংশন ব্যবহার করুন এবং তারপরে সেই নির্দিষ্ট ক্যাচ ব্লকে এটিকে কল করুন:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

26
মজাদার ধারণা এবং অন্য একটি উদাহরণ যা ভিবি.এন. এর মাঝে মাঝে সি # এর কিছু আকর্ষণীয় সুবিধা রয়েছে
মাইকেল স্টাম

47
সঙ্গে @MichaelStum যে বাক্য গঠন ধরনের আমি কমই এটা সব সময়ে ... আকর্ষণীয় কল করবে ভয়ে কাঁপে
MarioDS

17
ব্যতিক্রম ফিল্টারগুলি সি # 6 এ আসছে! উল্লেখ্য rethrowing পক্ষে ফিল্টার ব্যবহার পার্থক্য roslyn.codeplex.com/discussions/541301
আর্নি Deruwe

@ আরনেডেরুয়ে এই লিঙ্কটির জন্য আপনাকে ধন্যবাদ! আমি শুধু পুনরায় নিক্ষেপ না করতে আরো এক গুরুত্বপূর্ণ কারণ শিখেছি: throw e;ধ্বংস ক্ষেত্রে স্টেকট্র্যাস এবং callstack, throw;ধ্বংস "শুধুমাত্র" callstack (রেন্ডারিং বেহুদা ক্র্যাশ-ডাম্প!) একটি খুব ভাল কারণ ব্যবহারের তন্ন তন্ন যদি এটা এড়ানো যায়!
আনোরজাকেন

1
সি # 6 হিসাবে ব্যতিক্রম ফিল্টার উপলব্ধ! অবশেষে।
ড্যানি

134

সম্পূর্ণতার স্বার্থে, .NET 4.0 এর পরে কোডটি আবার লিখতে পারে:

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

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


সি # 7 যেহেতু আপনি একটি পৃথক লাইনে একটি ভেরিয়েবল প্রবর্তন এড়াতে পারবেন:

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

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

(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 তে কার্যকর করা হলে এই অকেজো উত্তরের পরবর্তী অকেজো আপডেট :)


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

9
আপনি কী বলতে চেয়েছিলেন তা আমি জানি, তবে অবশ্যই Guid.TryParseকখনই ফিরে আসে না Guid.Empty। যদি স্ট্রিংটি একটি ভুল ফর্ম্যাটে থাকে তবে এটি resultআউটপুট প্যারামিটারটিকে সেট করে Guid.Emptyতবে এটি ফিরে আসে false । আমি এটি উল্লেখ করছি কারণ আমি এমন কোড দেখেছি Guid.TryParse(s, out guid); if (guid == Guid.Empty) { /* handle invalid s */ }যা শৈলীতে কাজ করে যা সাধারণত ভুল হয় যদি sএর স্ট্রিং প্রতিনিধিত্ব হতে পারে Guid.Empty

14
বাহ আপনি প্রশ্নের উত্তর দিয়েছেন, ব্যতীত এটি প্রশ্নের চেতনা নয় except বৃহত্তর সমস্যা হ'ল অন্যরকম :(
নওফাল

6
অবশ্যই ট্রাই পার্সে ব্যবহারের উপযুক্ত প্যাটার্নটি আরও বেশি if( Guid.TryParse(s, out guid){ /* success! */ } else { /* handle invalid s */ }, যা ভাঙা উদাহরণের মতো অস্পষ্টতা রাখে না যেখানে ইনপুট মানটি সম্ভবত কোনও গাইডের স্ট্রিং প্রতিনিধিত্ব হতে পারে।
ক্রেগ

2
এই উত্তরটি গাইডের বিষয়ে সত্যই সঠিক হতে পারে ars পার্স, তবে এটি মূল প্রশ্নের পুরো বিষয়টি মিস করেছে। গাইডের সাথে পার্সের কোনও সম্পর্ক ছিল না, তবে ব্যতিক্রম ফর্ম্যাটএক্সসেপশন / ওভারফ্লো এক্সেকশন / ইত্যাদি ধরার বিষয়ে ছিল।
কনর গ্যালাগার

113

ব্যতিক্রম ফিল্টারগুলি এখন সি # 6+ এ উপলব্ধ। আপনি করতে পারেন

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

সি # 7.0+ এ আপনি একে প্যাটার্ন মেলানোর সাথেও সংযুক্ত করতে পারেন

try
{
   await Task.WaitAll(tasks);
}
catch (Exception ex) when( ex is AggregateException ae &&
                           ae.InnerExceptions.Count > tasks.Count/2)
{
   //More than half of the tasks failed maybe..? 
}

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

74

আপনি যদি নিজের আবেদনটি সি # 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 এর একমাত্র নতুন বৈশিষ্ট্য যা পূর্ববর্তী সংস্করণগুলিতে অনুকরণ করা সম্ভব নয়। প্রথমত, একটি রি-থ্রো মানে ক্যাচ এড়িয়ে যাওয়ার চেয়ে ওভারহেড। দ্বিতীয়ত, এটি শব্দার্থগতভাবে সমতুল্য নয়। আপনি নিজের কোডটি ডিবাগ করার সময় নতুন বৈশিষ্ট্যটি স্ট্যাকটি অক্ষত রাখে। এই বৈশিষ্ট্যটি ছাড়াই ক্র্যাশ ডাম্প কম দরকারী বা এমনকি অকেজো।

কোডপ্লেক্সে এ সম্পর্কে একটি আলোচনা দেখুন । এবং পার্থক্য দেখাচ্ছে একটি উদাহরণ


4
ব্যতিক্রম ছাড়াই নিক্ষেপ স্ট্যাকটি সংরক্ষণ করে তবে "থ্রো প্রাক্তন" এটিকে ওভাররাইট করে দেবে।
ইভান

32

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

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

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

আসলে, আপনি মূলত যে শর্তটি এই whenধারার ভিতরে রাখতে পারেন :

static int a = 8;

...

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

মনে রাখবেন যে এর স্কোপের ifভিতরে থাকা কোনও বক্তব্যের বিপরীতে catch, 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বিবৃতি, কিন্তু Filters, এবং Exceptionsএলাকার চিহ্নিত মধ্যে থেকে থ্রো হতে পারে না Filter 1এবং Filter 2কিন্তু ফিল্টার নিক্ষেপ Exceptionপরিবর্তে ব্যর্থ হবে, এছাড়াও গত তুলনা মান সামনে স্ট্যাক পর্যন্ত পিছিয়ে দেয় endfilterকমান্ড ফিল্টারটির সাফল্য / ব্যর্থতা নির্ধারণ করবে ( Catch 1 এক্সওআর Catch 2 সেই অনুযায়ী কার্যকর হবে):

ব্যতিক্রম ফিল্টারগুলি এমএসআইএল

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


ফিল্টার করার সময় একাধিক দেখানোর জন্য এবং একাধিক ফিল্টার যখন ব্যবহৃত হয় তখন কী ঘটে তার একটি ব্যাখ্যা সরবরাহ করার জন্য +1।
স্টিভেন 87vt

26

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

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

এবং সি # 8 সহ স্যুইচ এক্সপ্রেশন হিসাবে:

catch (Exception ex)
{
    WebId = ex switch
    {
        _ when ex is FormatException || ex is OverflowException => Guid.Empty,
        _ => throw ex
    };
}

3
এটি 2018 আইএমএইচও হিসাবে স্বীকৃত উত্তর হওয়া উচিত।
মেম্ফিজ

6
মাদুর জে'র উত্তরটি ব্যবহারের whenপরিবর্তে একটি স্যুইচের চেয়ে অনেক বেশি মার্জিত / উপযুক্ত।
rgoliveira

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

1
@ ফ্যাবিয়ান "যদি আপনার আলাদা কোড থাকে তবে আপনি ব্যতিক্রমের ধরণের উপর নির্ভর করে কার্যকর করতে চান বা যদি আপনি বাস্তবে ব্যতিক্রমের উদাহরণটি ব্যবহার করতে চান", তবে আপনি কেবল একটি আলাদা catchব্লক তৈরি করুন, বা আপনাকে যেভাবেই এটি কাস্ট করতে হবে .. আমার অভিজ্ঞতায়, throw;আপনার catchব্লকের একটি সম্ভবত কোডের গন্ধ।
rgoliveira

@rgoliveira: একটি ধরা ব্লক একটি থ্রো ব্যবহার ঠিক আছে বিভিন্ন ক্ষেত্রে দেখতে লিংক । যেহেতু কেস স্টেটমেন্টটি প্যাটার্ন ম্যাচিং লিঙ্কটি ব্যবহার করে আপনি যদি ভেরিয়েবল নামের দ্বারা বিলোপ অপারেটর লিঙ্ক (আন্ডারস্কোর) প্রতিস্থাপন করেন তবে আপনাকে castালাই করার দরকার নেই । আমাকে ভুল করবেন না, আমি আপনাদের সাথে একমত হই যে ব্যতিক্রম ফিল্টারগুলি এটির একটি পরিষ্কার উপায়, তবে একাধিক ক্যাচ ব্লকগুলি অনেকগুলি কোঁকড়ানো বন্ধনী যুক্ত করে।
ফ্যাবিয়ান

20

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

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

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

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

bool exThrown = false;

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

if (exThrown)
{
    // Something else
}

19
তবে সচেতন হন যে স্ট্যাকের ট্রেসটি আপনি যদি এটির মতো করে না ফেলে আপনি ব্যতিক্রমটি পুনর্হিত করতে পারবেন না। (গৃহীত উত্তরের জন্য মাইকেল স্টামের মন্তব্য দেখুন)
রেনে

2
এই প্যাটার্নটি ব্যতিক্রম সংরক্ষণ করে উন্নত করা যেতে পারে (দয়া করে খারাপ ফর্ম্যাটিংটি ক্ষমা করুন - মন্তব্যে কোড কীভাবে রাখবেন তা আমি বুঝতে পারি না): ব্যতিক্রম ex = নাল; চেষ্টা করুন {// কিছু} ধরা (ফর্ম্যাট এক্সপশন ই) {প্রাক্তন = ই; } ক্যাচ (ওভারফ্লো এক্সেকশন ই) {প্রাক্তন = ই; } যদি (প্রাক্তন! = নাল) {// অন্যরকম কিছু করুন এবং প্রাক্তনের সাথে ডিল করুন}
জেসি ওয়েইগার্ট

3
@ জেসি ওয়েইগার্ট: ১. আপনি এক টুকরো পাঠ্য মনো-ফাঁক ফন্ট এবং হালকা ধূসর ব্যাকগ্রাউন্ড দিতে ব্যাকটিক্স ব্যবহার করতে পারেন। ২. আপনি এখনও স্ট্যাকট্রেস সহ মূল ব্যতিক্রমটি পুনর্বিবেচনা করতে পারবেন না ।
অলিভার

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

3
কেবলমাত্র isঅপারেটর কর্মক্ষমতা হ্রাস করে যদি আপনি পরে কোনও asঅপারেশন করেন (অতএব তারা অকারণে নিয়মকে যোগ্য করে তোলে )। যদি আপনি যা করছেন সবই কাস্টটি সম্পাদন করার প্রয়োজন ছাড়াই কাস্টটি পরীক্ষা করা হয়, তবে isঅপারেটরটি হ'ল আপনি যা ব্যবহার করতে চান তা ঠিক।
13:25

19

সি # 6 এ প্রস্তাবিত পদ্ধতির ব্যতিক্রম ফিল্টারগুলি ব্যবহার করা হয়, এখানে একটি উদাহরণ রয়েছে:

 try
 {
      throw new OverflowException();
 }
 catch(Exception e ) when ((e is DivideByZeroException) || (e is OverflowException))
 {
       // this will execute iff e is DividedByZeroEx or OverflowEx
       Console.WriteLine("E");
 }

18

এটি ম্যাট এর উত্তরের একটি বৈকল্পিক (আমার মনে হচ্ছে এটি কিছুটা পরিষ্কার) ... একটি পদ্ধতি ব্যবহার করুন:

public void TryCatch(...)
{
    try
    {
       // something
       return;
    }
    catch (FormatException) {}
    catch (OverflowException) {}

    WebId = Guid.Empty;
}

অন্য কোনও ব্যতিক্রম নিক্ষেপ করা হবে এবং কোডটি WebId = Guid.Empty;আঘাত করা হবে না। আপনি যদি নিজের প্রোগ্রামটি ক্র্যাশ করতে চান না তবে অন্যান্য দুটি ক্যাচের পরে এটি যুক্ত করুন:

...
catch (Exception)
{
     // something, if anything
     return; // only need this if you follow the example I gave and put it all in a method
}

-1 এটি WebId = Guid.Emtpyক্ষেত্রে কার্যকর হবে যেখানে কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয়নি।
সেপ্টেম্বর

4
@ সেপস্টার আমি "// কিছু" পরে রিটার্নের বিবৃতি এখানে অন্তর্ভুক্ত বলে মনে করি। সমাধানটি আমি সত্যিই পছন্দ করি না তবে এটি আলোচনার ক্ষেত্রে গঠনমূলক রূপ iant আপনার ডাউনটোটটি পূর্বাবস্থায় নেওয়ার জন্য +1 :-)
23'12

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

18

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

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

    // Handle exception
}

এক্সপ্রেশনটি উল্টানোর কয়েকটি সুবিধা রয়েছে:

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

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

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

    // Handle exception
}

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

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

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

2
+1, এটি সেরা উত্তর। এটি শীর্ষ জবাবের চেয়ে বেশিরভাগই ভাল কারণ বেশিরভাগই নেই return, যদিও শর্তটি উল্টানোও কিছুটা ভাল।
ডিসিএসনন

আমি এটা ভাবিনি। ভাল ক্যাচ, আমি এটিকে তালিকায় যুক্ত করব।
স্টেফান টি

16

@Micheal

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

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

স্ট্রিং তুলনা কুরুচিপূর্ণ এবং ধীর।


21
শুধু "কী" কীওয়ার্ডটি ব্যবহার করবেন না কেন?
ক্রিস পিটসমান 21

29
@ মিশেল - মাইক্রোসফ্ট যদি পরিচয় করিয়ে দেয় তবে বলুন যে স্ট্রিংটলংএক্সসেপশন ফর্ম্যাটএক্সসেপশন থেকে উদ্ভূত হয়েছে তবে এটি এখনও একটি ফর্ম্যাট ব্যতিক্রম, কেবল একটি নির্দিষ্ট one আপনি 'এই সঠিক ব্যতিক্রম ধরুন' বা 'ব্যতিক্রম ধরা যার অর্থ স্ট্রিংটির ফর্ম্যাটটি ভুল ছিল' এর শব্দার্থকগুলি চান কিনা তা নির্ভর করে।
গ্রেগ বিচ 21

6
@ মিশেল - এছাড়াও, নোট করুন যে "ক্যাচ (ফরম্যাটএক্সসেপশন প্রাক্তন) পরবর্তী শব্দার্থবিজ্ঞান রয়েছে, এটি ফর্ম্যাটএক্সেপশন থেকে প্রাপ্ত যে কোনও কিছুই ধরবে।
গ্রেগ বিচ

14
অ্যালেক্স নং "প্র" কে "প্রাক্তন" ছাড়াই মূল স্ট্যাক ট্রেস সহ মূল ব্যতিক্রম বহন করে। "প্রাক্তন" যোগ করা স্ট্যাক ট্রেসটিকে পুনরায় সেট করে তোলে, তাই আপনি আসলটির চেয়ে সত্যিই আলাদা ব্যতিক্রম পান। আমি নিশ্চিত যে আমার চেয়ে আরও ভাল কেউ এর ব্যাখ্যা দিতে পারে। :)
সামান্থা ব্রানহাম

13
-1: এই কোড অত্যন্ত ভঙ্গুর হয় - একটি লাইব্রেরি ডেভেলপার প্রতিস্থাপন আশা করতে পারে throw new FormatException();সঙ্গে throw new NewlyDerivedFromFormatException();লাইব্রেরি ব্যবহার কোড ভঙ্গ ছাড়া, এবং এটি সমস্ত ব্যতিক্রম ছাড়া যেখানে কেউ ব্যবহার ক্ষেত্রেই পরিচালনা করার জন্য সত্য ধরে নেবে ==পরিবর্তে is(বা শুধু catch (FormatException))।
স্যাম হারওয়েল

13

কেমন

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

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

4
সেক্ষেত্রে আমি একটি রিসেট ফাংশন যুক্ত করব এবং একাধিক ক্যাচ ব্লক থেকে কল করব।
মরিস


11

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

লিঙ্কটিতে যা রয়েছে তা আপনার প্রশ্নের সরাসরি উত্তর দেয় না তবে এটি দেখতে এটি প্রসারিত করা তুচ্ছ:

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

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

(মূলত অন্য খালি Catchওভারলোড সরবরাহ করুন যা নিজেই ফিরে আসে)

এটি আরও বড় প্রশ্ন কেন । আমি মনে করি না যে ব্যয়টি এখানে লাভের চেয়ে বেশি হয়ে গেছে :)


1
এই পদ্ধতির একটি সম্ভাব্য সুবিধা হ'ল এটি ধরতে না পেরে কোনও ব্যতিক্রম ধরা ও পুনর্বিবেচনার মধ্যে অর্থপূর্ণ পার্থক্য রয়েছে; কিছু ক্ষেত্রে কোডটি এটি ধরা না দিয়ে ব্যতিক্রম হিসাবে কাজ করা উচিত । এই জাতীয় জিনিস vb.net- এ সম্ভব, তবে সি # তে নয়, যদি না কেউ ভিবিএন.তে লিখিত র‌্যাপার ব্যবহার করে এবং সি # থেকে কল না করে।
সুপারক্যাট

1
এটি ধরা না দিয়ে কীভাবে ব্যাতিক্রম করে? আমি আপনাকে পুরোপুরি বুঝতে পারি না।
নওফাল

@ নওফুল ... ভিবি ফিল্টার ব্যবহার করে - ফাংশন ফিল্ট (ব্যতিক্রম হিসাবে প্রাক্তন): লগএক্স (প্রাক্তন): মিথ্যা প্রত্যাবর্তন করুন ... তারপরে ক্যাচ লাইনে: ক্যাট এক্স যখন ফিল্ট (প্রাক্তন)
ফাস্টএল

1
@ ফস্টএল এটি কি ব্যতিক্রম-ফিল্টারগুলি সি # 6 এ অনুমতি দেয়?
হিমব্রুমবিয়ার

@HimBromBeere হাঁ তারা সরাসরি অনুরূপ উদাহরণ করছি
FastAl

9

2015-12-15 আপডেট করুন: সি # 6 এর জন্য https://stackoverflow.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(StackOverflowException)))
                    throw;

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

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

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

এছাড়াও নোট করুন, আপনার সমাধানটি কেবলমাত্র # # এর শব্দার্থতত্ত্বের সমতুল্য when, যেমন কোনও সংস্করণ হিসাবে catch (Exception ex) {if (...) {/*handle*/} throw;}। এর আসল মানটি whenহ'ল ব্যতিক্রমটি ধরা পড়ার আগে ফিল্টারটি চালিত হয়, যাতে পুনরায় নিক্ষেপের ব্যয় / স্ট্যাক দুর্নীতি এড়ানো যায়। এটি এমন সিএলআর বৈশিষ্ট্যটি গ্রহণ করে যা কেবল আগে ভিবি এবং এমএসআইএল-এ প্রবেশযোগ্য ছিল।
মার্ক এল।

আরও মার্জিত? এই সাধারণ সমস্যাটির জন্য এই উদাহরণটি এত বড় এবং কোডটি এত ভয়াবহ দেখাচ্ছে যে এটি চেহারা দেওয়ার মতোও নয়। দয়া করে এই কোডটি কোনও আসল প্রকল্পে অন্য কারও সমস্যা তৈরি করবেন না।
KthProg

আপনার সম্পূর্ণ IsAnyOfপদ্ধতিটি সহজভাবে পুনরায় লেখা যেতে পারেp_comparisons.Contains(p_parameter)
maksymiuk

7

যেহেতু আমার মনে হয়েছে যে এই উত্তরগুলি কেবল পৃষ্ঠের উপরে স্পর্শ করেছে, তাই আমি আরও গভীর খননের চেষ্টা করেছি।

সুতরাং আমরা যা করতে চাই তা হ'ল এমন কিছু যা সংকলন করে না, বলুন:

// Won't compile... damn
public static void Main()
{
    try
    {
        throw new ArgumentOutOfRangeException();
    }
    catch (ArgumentOutOfRangeException)
    catch (IndexOutOfRangeException) 
    {
        // ... handle
    }

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

তাহলে কেন এই কোডটি সংকলন করবে না - এবং আমরা কীভাবে এটি এমনভাবে হ্যাক করব?

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

বা কোডটিতে এটি লিখতে, আমরা সংকলককে এই জাতীয় কিছু করতে বলি (ভাল এটি সম্পূর্ণ সঠিক নয়, তবে এটি আমার অনুমানের সবচেয়ে কাছের জিনিস):

// Won't compile... damn
try
{
    throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException e) {
    goto theOtherHandler;
}
catch (IndexOutOfRangeException e) {
theOtherHandler:
    Console.WriteLine("Handle!");
}

এটি সংকলন না করার কারণটি পুরোপুরি সুস্পষ্ট: '$ ব্যতিক্রম' অবজেক্টটির কী ধরণের এবং মান হবে (যা এখানে ভেরিয়েবল 'ই' তে সংরক্ষিত আছে)? আমরা যেভাবে সংকলকটি পরিচালনা করতে চাই তা লক্ষ্য করা যায় যে উভয় ব্যতিক্রমের সাধারণ বেস প্রকারটি 'ব্যতিক্রম', দুটি ব্যতিক্রম ধারণ করতে একটি ভেরিয়েবলের জন্য এটি ব্যবহার করুন এবং তারপরে কেবল দুটি ব্যতিক্রমই ধরা যাক। আইএলটিতে এটি যেভাবে প্রয়োগ করা হয়েছে তা হ'ল ফিল্টার হিসাবে, যা ভিবি.নেটে উপলব্ধ।

এটি সি # তে কাজ করার জন্য, আমাদের সঠিক 'ব্যতিক্রম' বেস টাইপ সহ একটি অস্থায়ী পরিবর্তনশীল প্রয়োজন। কোডের প্রবাহ নিয়ন্ত্রণ করতে আমরা কয়েকটি শাখা যুক্ত করতে পারি। এখানে যায়:

    Exception ex;
    try
    {
        throw new ArgumentException(); // for demo purposes; won't be caught.
        goto noCatch;
    }
    catch (ArgumentOutOfRangeException e) {
        ex = e;
    }
    catch (IndexOutOfRangeException e) {
        ex = e;
    }

    Console.WriteLine("Handle the exception 'ex' here :-)");
    // throw ex ?

noCatch:
    Console.WriteLine("We're done with the exception handling.");

এর সুস্পষ্ট অসুবিধাগুলি হ'ল আমরা সঠিকভাবে পুনরায় নিক্ষেপ করতে পারি না, এবং আসুন সত্য কথা বলা যাক - এটি বেশ কুৎসিত সমাধান। কদর্যতা শাখা নির্মূলের মাধ্যমে কিছুটা সংশোধন করা যেতে পারে, যা সমাধানটি কিছুটা আরও ভাল করে তোলে:

Exception ex = null;
try
{
    throw new ArgumentException();
}
catch (ArgumentOutOfRangeException e)
{
    ex = e;
}
catch (IndexOutOfRangeException e)
{
    ex = e;
}
if (ex != null)
{
    Console.WriteLine("Handle the exception here :-)");
}

এটি কেবল 'পুনরায় নিক্ষেপ' ছাড়বে। এটি কাজ করার জন্য, আমাদের 'ধরা' ব্লকের ভিতরে হ্যান্ডলিং সম্পাদন করতে সক্ষম হওয়া দরকার - এবং এই কাজটি করার একমাত্র উপায় হ'ল ক্যাচিং 'ব্যতিক্রম' অবজেক্ট by

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

private static bool Handle(Exception e)
{
    Console.WriteLine("Handle the exception here :-)");
    return true; // false will re-throw;
}

public static void Main()
{
    try
    {
        throw new OutOfMemoryException();
    }
    catch (ArgumentException e)
    {
        if (!Handle(e)) { throw; }
    }
    catch (IndexOutOfRangeException e)
    {
        if (!Handle(e)) { throw; }
    }

    Console.WriteLine("We're done with the exception handling.");

এবং অন্য সমাধানটি হ'ল ব্যতিক্রমী জিনিসটি ধরা এবং সেই অনুযায়ী পরিচালনা করুন। উপরোক্ত প্রসঙ্গের ভিত্তিতে এর জন্য সবচেয়ে আক্ষরিক অনুবাদটি হ'ল:

try
{
    throw new ArgumentException();
}
catch (Exception e)
{
    Exception ex = (Exception)(e as ArgumentException) ?? (e as IndexOutOfRangeException);
    if (ex != null)
    {
        Console.WriteLine("Handle the exception here :-)");
        // throw ?
    }
    else 
    {
        throw;
    }
}

সুতরাং উপসংহারে:

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

7

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

আমাকে আপনার প্রশ্নটি 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) {}

যদি কোনও ব্যতিক্রম ছুঁড়ে ফেলা হয়, তবে ওয়েবআইডি কখনও অর্ধ-নির্মিত মান হিসাবে সেট করা হয় না এবং গাইড হিসাবে থাকে mp

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

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

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

6

সুতরাং আপনি প্রতি ব্যতিক্রম-সুইচ মধ্যে প্রচুর কোড পুনরাবৃত্তি করছেন? কোনও পদ্ধতিতে উত্তোলনের মতো শব্দগুলি ideaশ্বরের ধারণা হবে, তাই না?

সুতরাং আপনার কোড এই নেমে আসে:

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 থেকে আপনার কাছে ইতিমধ্যে অন্যদের দ্বারা উল্লিখিত ব্যতিক্রম-ফিল্টার রয়েছে। সুতরাং আপনি উপরের কোডটি এতে পরিবর্তন করতে পারেন:

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

3
"আমি অবাক হয়েছি কেন কেন কেউ সেই কোড-নকলটি লক্ষ্য করেনি?" - আহ, কি? প্রশ্নই সমগ্র বিন্দু কোড প্রতিলিপি নিষ্কাশন হয়।
মার্ক

4

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

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

            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);
            }

আমি লোকদের এই এমএসডিএন ডকুমেন্টটি পর্যালোচনা করার জন্য অত্যন্ত পরামর্শ দিচ্ছি:

ব্যতিক্রম হায়ারার্কি


4

আপনার কোডটি সহজ রাখার চেষ্টা করুন যেমন কোনও পদ্ধতিতে সাধারণ কোড স্থাপন করা যেমন আপনি কোডের অন্য কোনও অংশে করেন যা কোনও ক্যাচ ক্লজের অভ্যন্তরে নেই?

উদাহরণ:

try
{
    // ...
}
catch (FormatException)
{
    DoSomething();
}
catch (OverflowException)
{
    DoSomething();
}

// ...

private void DoSomething()
{
    // ...
}

আমি কীভাবে এটি করব, সহজটি সন্ধান করার চেষ্টা করা হচ্ছে সুন্দর ধরণ


3

নোট করুন যে আমি এটি করার একটি উপায় খুঁজে পেয়েছি তবে এটি ডেইলি ডাব্লুটিএফের জন্য আরও উপাদানের মতো দেখাচ্ছে :

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

9
-1 ভোট, +5 ডাব্লুটিএফ :-) এটিকে উত্তর হিসাবে চিহ্নিত করা উচিত নয়, তবে এটি প্রচণ্ড লরিয়াস।
হারুন 21

1
আমরা কীভাবে সহজভাবে এটি করতে পারি তা বিবেচ্য নয়। কিন্তু তিনি অলস বসে না এবং এটি সমাধান করার জন্য তাঁর দৃষ্টিভঙ্গি নিয়ে এসেছিলেন। সত্যিই কৃতজ্ঞ.
ম্যাক্সিমাস

2
বাস্তবে এটি করবেন না, সি # 6 বা অন্য যে কোনও উত্তরের ব্যতিক্রম ফিল্টারগুলি ব্যবহার করুন - আমি এখানে এটি বিশেষত "এটি একটি উপায়, তবে এটি খারাপ এবং আমি আরও ভাল কিছু করতে চাই" হিসাবে এইগুলি রেখেছি।
মাইকেল স্টাম

কেন এই খারাপ? আমি বিস্মিত হয়েছি আপনি সরাসরি একটি স্যুইচ বিবৃতিতে ব্যতিক্রমটি ব্যবহার করতে পারবেন না।
এমকেস্পার

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

2

এটি এখানে উল্লেখযোগ্য। আপনি একাধিক সংমিশ্রণগুলিতে প্রতিক্রিয়া জানাতে পারেন (ব্যতিক্রম ত্রুটি এবং ব্যতিক্রম me ম্যাসেজ)।

টেক্সটবক্স, টেক্সটব্লক বা চেকবক্স হিসাবে সামগ্রী হিসাবে কোনও একটি ডেটাগ্রিডে কন্ট্রোল অবজেক্ট কাস্ট করার চেষ্টা করার সময় আমি একটি ব্যবহারের ক্ষেত্রে দৃশ্যে পৌঁছেছি। এই ক্ষেত্রে ফিরে আসা ব্যতিক্রম একই ছিল, তবে বার্তাটি ভিন্ন।

try
{
 //do something
}
catch (Exception ex) when (ex.Message.Equals("the_error_message1_here"))
{
//do whatever you like
} 
catch (Exception ex) when (ex.Message.Equals("the_error_message2_here"))
{
//do whatever you like
} 

0

আমি সংক্ষিপ্ত উত্তরটির পরামর্শ দিতে চাই (আরও একটি কার্যকরী শৈলী ):

        Catch<FormatException, OverflowException>(() =>
            {
                WebId = new Guid(queryString["web"]);
            },
            exception =>
            {
                WebId = Guid.Empty;
            });

এর জন্য আপনাকে সিস্টেমের অনুরূপ বেশ কয়েকটি "ক্যাচ" পদ্ধতি ওভারলোডগুলি তৈরি করতে হবে।

    [DebuggerNonUserCode]
    public static void Catch<TException1, TException2>(Action tryBlock,
        Action<Exception> catchBlock)
    {
        CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2));
    }

    [DebuggerNonUserCode]
    public static void Catch<TException1, TException2, TException3>(Action tryBlock,
        Action<Exception> catchBlock)
    {
        CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2), typeof(TException3));
    }

এবং তাই আপনি চান হিসাবে অনেক। তবে আপনাকে এটি একবার করতে হবে এবং আপনি এটি আপনার সমস্ত প্রকল্পে ব্যবহার করতে পারেন (বা, আপনি যদি কোনও নুগেট প্যাকেজ তৈরি করেন তবে আমরা এটিও ব্যবহার করতে পারি)।

এবং ক্যাচমনির বাস্তবায়ন:

    [DebuggerNonUserCode]
    public static void CatchMany(Action tryBlock, Action<Exception> catchBlock,
        params Type[] exceptionTypes)
    {
        try
        {
            tryBlock();
        }
        catch (Exception exception)
        {
            if (exceptionTypes.Contains(exception.GetType())) catchBlock(exception);
            else throw;
        }
    }

PS আমি কোড সরলতার জন্য নাল চেক রাখিনি, প্যারামিটারের বৈধতাগুলি বিবেচনা করার জন্য বিবেচনা করুন।

PS2 আপনি যদি ক্যাচ থেকে কোনও মান ফিরিয়ে দিতে চান তবে একই ক্যাচ পদ্ধতিগুলি করা দরকার তবে পরামিতিগুলিতে অ্যাকশনের পরিবর্তে রিটার্ন এবং ফানক দিয়ে।


-15

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

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

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


3
উম। এটি প্রশ্নের উদ্দেশ্যকে পরাজিত করছে। তিনি এই প্রশ্নটি সদৃশ কোড থেকে মুক্তি পেতে জিজ্ঞাসা করলেন। এই উত্তরটি আরও নকল কোড যুক্ত করে।
জেমস এশ

-23

সি # 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");
    }
}

13
এই উদাহরণ ব্যতিক্রম ফিল্টারগুলির কোনও ব্যবহার দেখায় না।
ব্যবহারকারী 247702

এটি সি # 6.0 এ ব্যতিক্রম ফিল্টার করার স্ট্যান্ডার্ড উপায়
কাশিফ

5
ঠিক কী ব্যতিক্রম ফিল্টারগুলি তা আবার দেখুন। আপনি আপনার উদাহরণে একটি ব্যতিক্রম ফিল্টার ব্যবহার করছেন না। আপনার উত্তরের এক বছর আগে পোস্ট করা উত্তরের একটি যথাযথ উদাহরণ রয়েছে ।
ব্যবহারকারী 247702

6
ব্যতিক্রম ফিল্টারিং একটি উদাহরণ হবেcatch (HttpException e) when e.GetHttpCode() == 400 { WriteLine("Bad Request"; }
saluce
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.