එකවර බහු ව්‍යතිරේක අල්ලා ගන්න?


2150

සරලව අල්ලා ගැනීම අධෛර්යමත් කරයි 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 සහ ඊට ඉහළින් භාවිතා කරන්නේ නම් මම සමස්තයක් ලෙස භාවිතා කිරීමට කැමැත්තෙමි msdn.microsoft.com/en-us/library/system.aggregateexception.aspx
Bepenfriends

2
Bepenfriends- System.Guid විසින් AggregateException විසි නොකරන බැවින් , ඔබට එය (හෝ යමෙකුට) AggregateException යනාදිය තුළට ඔතා තබන ආකාරය පෙන්වන පිළිතුරක් පළ කළ හැකි නම් එය ඉතා හොඳ වේ.
weir

1
භාවිතා කරන විට AggregateException: මගේ කේතයට
සමස්ථ විග්‍රහයක්

11
"හුදෙක් System.Exception අල්ලා ගැනීම අධෛර්යමත් කරනු ලැබේ." ක්‍රමයට ව්‍යතිරේක 32 ක් විසි කළ හැකි නම්, කුමක් කරන්නේ ද? එක් එක් සඳහා වෙන වෙනම ඇල්ලීම ලියන්න?
ජෝජිම්

5
ක්‍රමයක් මඟින් විවිධ වර්ගයේ ව්‍යතිරේක 32 ක් විසි කරන්නේ නම්, එය නරක ලෙස ලියා ඇත. එය එක්කෝ තමන්ගේම ඇමතුම් ලබා ගන්නා ව්‍යතිරේකයන් හසු කර නොගැනීම, එය එක් ක්‍රමයකින් FAR වැඩිපුර කිරීම හෝ බහුතරය / ඒ 32 දෙනාටම හේතු කේතයක් සහිත තනි ව්‍යතිරේකයක් විය යුතුය.
ෆ්ලින් 1179

Answers:


2108

වර්ග අල්ලාගෙන System.Exceptionමාරු වන්න

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

    throw;
}

70
අවාසනාවට, ඔබ ව්‍යතිරේකය අල්ලා ගන්නා විට FxCop (එනම් - දෘශ්‍ය ස්ටුඩියෝ කේත විශ්ලේෂණය) එයට කැමති නැත.
ගැරිසන්

17
ව්‍යතිරේකය අල්ලා නොගැනීමට මම එකඟ වෙමි, නමුත්, මේ අවස්ථාවේ දී, අල්ලා ගැනීම පෙරණයකි. ඔබට වෙනත් ව්‍යතිරේක වර්ග හැසිරවිය හැකි ඉහළ තට්ටුවක් තිබිය හැක. අල්ලා ගැනීමක් (ව්‍යතිරේකය x) ඇතුළත් වුවද මෙය නිවැරදි යැයි මම කියමි. එය ක්‍රමලේඛ ප්‍රවාහය වෙනස් නොකරයි, එය යම් යම් ව්‍යතිරේකයන් හසුරුවන අතර ඉතිරි යෙදුම් වෙනත් ව්‍යතිරේක වර්ග සමඟ ගනුදෙනු කිරීමට ඉඩ දෙයි.
lkg

29
ඉහත කේතය භාවිතා කරන විට FxCop හි නවතම අනුවාදය ව්‍යතිරේකයක් නොදක්වයි.
පීටර්

28
මුලින් OP කේතයේ වැරැද්ද කුමක්දැයි විශ්වාස නැත. # 1 පිළිගත් පිළිතුර පේළි මෙන් දෙගුණයක් වන අතර කියවිය හැකි තරම් අඩුය.
ජොආනෝ බ්‍රගානියා

22
@ JoãoBragança: මෙම උදාහරණයේ ඇති පිළිතුර තවත් පේළි භාවිතා කරන අතර, ඔබ උදාහරණයක් ලෙස IO ගොනුව සමඟ ගනුදෙනු කරන්නේ දැයි සිතා බැලීමට උත්සාහ කරන්න, ඔබට කිරීමට අවශ්‍ය වන්නේ එම ව්‍යතිරේකයන් අල්ලාගෙන ලොග් පණිවිඩ යැවීම පමණි, නමුත් ඔබෙන් බලාපොරොත්තු වන්නේ ඒවායින් පමණි ගොනු IO ක්‍රම. එවිට ඔබට බොහෝ විට විශාල සංඛ්‍යාවක් (5 ක් හෝ ඊට වැඩි) විවිධ වර්ගයේ ව්‍යතිරේකයන් සමඟ කටයුතු කිරීමට සිදුවේ. එවැනි තත්වයක් තුළ, මෙම ප්‍රවේශය මඟින් ඔබට පේළි කිහිපයක් ඉතිරි කළ හැකිය.
Xilconic

601

සංස්කරණය කරන්න: C # 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 ඇති බව ඔබගේ කේතය කිරීමට විශ්ලේෂණයක් එකතු කරන්න, සහ රෝගීන් 99.9% ක දී එය මුළුමනින්ම බව ප්රශ්නයක් නොසලකා FxCop කියන්න ඇත්තේ එකම සලකුණු කිරීමේදී නිවැරදි. කණගාටුයි, මම වැරදියට තේරුම් ගත හැකිය, නමුත් එම "නොසලකා හැරීමේ" ගුණාංගය ඇත්ත වශයෙන්ම ඔබේ යෙදුමට සම්පාදනය නොවේද?

සමස්තයක්ම තබයි if පරීක්ෂණය එක පේළියකට එය වඩාත් කියවිය හැකි ද? මම හිතන්නේ නැහැ. මම අදහස් කළේ, තවත් ක්‍රමලේඛකයෙකු බොහෝ කලකට පෙර දැඩි ලෙස තර්ක කර ඇත්තේ එක් පේළියක තවත් කේතයක් තැබීමෙන් එය “වේගයෙන් ධාවනය” වනු ඇති බවයි. නමුත් ඇත්ත වශයෙන්ම ඔහු තදින් කෑ ගැසුවේය. ඔහුට පැහැදිලි කිරීමට උත්සාහ කිරීම (face ජු මුහුණකින් - අභියෝගාත්මක විය) පරිවර්තකයා හෝ සම්පාදකයා එම දිගු රේඛාව විවික්ත එක්-උපදෙස්-එක්-පේළි ප්‍රකාශවලට වෙන් කරන්නේ කෙසේද - ඔහු ඉදිරියට ගොස් ඇත්නම් සහ ප්‍රති result ලයට සමාන වේ. සම්පාදකයාට වඩා දක්ෂ ලෙස උත්සාහ කිරීම වෙනුවට කේතය කියවිය හැකි ලෙස සකසා ඇත - ඔහුට කිසිදු බලපෑමක් සිදු නොවීය. නමුත් මම කණගාටු වෙමි.

ඔබ දැන් සිට තවත් ව්‍යතිරේක වර්ග තුනක්, මාසයක් හෝ දෙකක් එකතු කළ විට මෙය කියවිය හැක්කේ කෙතරම් අඩු ද ? (පිළිතුර: එය ලැබෙන ගොඩක් අඩු කියවිය හැකි).

එක් ප්‍රධාන කරුණක් නම්, අප සෑම දිනකම බලා සිටින පෙළ මූලාශ්‍ර කේතය සංයුති කිරීමේ බොහෝ කරුණ නම්, කේතය ක්‍රියාත්මක වන විට සත්‍ය වශයෙන්ම සිදුවන්නේ කුමක්ද යන්න අනෙක් මිනිසුන්ට සැබවින්ම පැහැදිලිව දැක්වීමයි. සම්පාදකයා ප්‍රභව කේතය මුළුමනින්ම වෙනස් දෙයක් බවට හරවන අතර ඔබේ කේත හැඩතල ගැන්වීමේ විලාසය ගැන එතරම් තැකීමක් කළ නොහැක. ඒ නිසා සෑම පේළියක්ම මුළුමනින්ම උරා ගනී.

කියමින් ...

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

37
මම මුලින්ම මෙම ප්‍රශ්නය පැකිලෙන විට පිළිගත් පිළිතුර පුරාම සිටියෙමි. සිසිල් මට සියලු දේ අල්ලා ගත හැකි Exceptionඅතර වර්ගය පරීක්ෂා කරන්න. මම සිතුවේ එය කේතය පිරිසිදු කර ඇති බවයි, නමුත් යමක් මා නැවත ප්‍රශ්නයට යොමු කරවන අතර ඇත්ත වශයෙන්ම මම ප්‍රශ්නයට අනෙක් පිළිතුරු කියවා ඇත්තෙමි. මම ටික වේලාවක් එය හපන නමුත් මට ඔබ සමඟ එකඟ විය යුතුය. සෑම දෙයක්ම අල්ලා ගැනීමට වඩා ඔබේ කේතය වියළීමට ශ්‍රිතයක් භාවිතා කිරීම, ලැයිස්තුවක් හා සැසඳීමේ වර්ගය පරීක්ෂා කිරීම, කේතය ඔතා තැබීම සහ විසි කිරීම වඩා කියවිය හැකි සහ නඩත්තු කළ හැකි ය. ප්‍රමාද වී පැමිණ විකල්ප සහ බුද්ධිමත් (IMO) විකල්පයක් ලබා දීම ගැන ස්තූතියි. +1.
වැරදි

8
ඔබට ඇතුළත් කිරීමට අවශ්‍ය නම් දෝෂ හැසිරවීමේ කාර්යයක් භාවිතා නොකරනු ඇත throw;. සෑම කේත කාණ්ඩයකම ඔබට එම කේත රේඛාව පුනරාවර්තනය කිරීමට සිදුවේ (පැහැදිලිවම ලෝකයේ අවසානය නොව එය නැවත නැවත කළ යුතු කේතයක් බැවින් සඳහන් කිරීම වටී).
kad81

5
ad kad81, එය සත්‍යයකි, නමුත් ඔබට තවමත් ල ging ු-සටහන් සහ පිරිසිදු කිරීමේ කේතය එක තැනක ලිවීමේ වාසිය ලැබෙනු ඇත, සහ අවශ්‍ය නම් එය එක තැනකට වෙනස් කිරීම, මූලික ව්‍යතිරේක වර්ගය අල්ලා ගැනීමේ විකාර අර්ථකථන නොමැතිව, පසුව අතු බෙදී යාම ව්‍යතිරේක වර්ගය. throw();සෑම ඇල්ලීමේ කොටසකම එක් අමතර ප්‍රකාශයක් ගෙවීමට ඇති කුඩා මිලක් වන IMO, අවශ්‍ය නම් අතිරේක ව්‍යතිරේක වර්ගයට විශේෂිත පිරිසිදු කිරීමක් කිරීමට ඔබව තවමත් ඉතිරි කරයි.
ක්‍රේග්

2
හායි e රීට්ෆන්ක්, Func<Exception, MyEnumType>ඒ වෙනුවට භාවිතා කරන්න Action<Exception>. එනම් Func<T, Result>, Resultආපසු එන වර්ගය වීමත් සමඟ .
ක්‍රේග්

3
මම මෙහි සම්පූර්ණ එකඟතාවයකින් සිටිමි. මමත් පළමු පිළිතුර කියවා සිතුවිල්ල තර්කානුකූලයි. සියලු ව්‍යතිරේක හසුරුවන්නන් සඳහා සාමාන්‍ය 1 වෙත ගෙන යන ලදි. මගේ ඇතුළත යමක් මා අභ්‍යන්තරව තල්ලු කළේය ... එබැවින් මම කේතය ආපසු හරවා යැව්වෙමි. එහෙනම් මේ සුන්දරත්වය හමුවුණා! මෙම අවශ්යතා විසින් පිළිගත් පිළිතුර විය
Conor මහතාගේ තනතුර සදහා ගලගර් මහතා පත්වන

377

අනෙක් අය පෙන්වා දී ඇති පරිදි, ifසිදුවන්නේ කුමක්ද යන්න තීරණය කිරීම සඳහා ඔබේ ඇල්ලීමේ කොටස තුළ ප්‍රකාශයක් ලබා ගත හැකිය . C # 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 දිගටම භාවිතා කිරීමට අවශ්‍ය නම්, ඔබට පහත දැක්වෙන නූගට් පැකේජය ස්ථාපනය කළ හැකිය:

ස්ථාපනය-පැකේජය Microsoft.Net.Compilers

ලිවීමේදී, C # 6 සඳහා සහය මෙයට ඇතුළත් වේ.

මෙම පැකේජය යොමු කිරීම මඟින් පද්ධතිය ස්ථාපනය කර ඇති ඕනෑම අනුවාදයකට වඩා පැකේජයේ අඩංගු C # සහ දෘශ්‍ය මූලික සම්පාදකයින්ගේ නිශ්චිත අනුවාදය භාවිතා කරමින් ව්‍යාපෘතිය තැනීමට හේතු වේ.


3
6 හි නිල නිකුතුව සඳහා ඉවසීමෙන් බලා සිටිමි ... එය සිදු වූ විට මෙය පරීක්‍ෂා කර බැලීමට මම කැමතියි.
රබර් ඩක්

Ub රබර් ඩක් මම සී # 6 සිට ශුන්‍ය ප්‍රචාරක ක්‍රියාකරු වෙනුවෙන් මිය යමි. අස්ථායී භාෂාවක් / සම්පාදකයෙකුගේ අවදානම වටින බව මගේ කණ්ඩායමේ සෙසු අයට ඒත්තු ගැන්වීමට උත්සාහ කිරීම. විශාල බලපෑමක් සහිත සුළු වැඩිදියුණු කිරීම් ගොඩක්. පිළිතුරක් ලෙස සලකුණු කිරීම වැදගත් නොවේ, මිනිසුන් මෙම කැමැත්ත / හැකි බව වටහා ගන්නා තාක් කල්, මම සතුටු වෙමි.
ජෝ

හරිද ?! මම නුදුරු අනාගතයේ දී මගේ කේත පදනම දෙස හොඳින් බලන්නෙමි. =) චෙක්පත වැදගත් නොවන බව මම දනිමි, නමුත් පිළිගත් පිළිතුර ඉක්මනින් යල් පැන ගිය එකක් වනු ඇතැයි මම විශ්වාස කරමි, නිසි දෘශ්‍යතාවයක් ලබා දීම සඳහා OP මෙය පරීක්ෂා කිරීමට නැවත පැමිණේ.
රබර් ඩක්

ඒ නිසාම මම තවමත් එය ප්‍රදානය නොකළේ @ ජෝ. මට මෙය දෘශ්‍යමාන වීමට අවශ්‍යයි. පැහැදිලි බව සඳහා පේළිගත කිරීමේ පෙරනයක් සඳහා උදාහරණයක් එක් කිරීමට ඔබට අවශ්‍ය විය හැකිය.
රබර් ඩක්

188

අවාසනාවකට C # හි නොවේ, ඔබට එය කිරීමට ව්‍යතිරේක පෙරණයක් අවශ්‍ය වන අතර C # MSIL හි එම අංගය හෙළි නොකරයි. VB.NET ට මෙම හැකියාව ඇතත්, උදා

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

ඔබට කළ හැකි වන්නේ ඔබගේ වැරදි කේතය සංකේතවත් කිරීම සඳහා නිර්නාමික ශ්‍රිතයක් භාවිතා කිරීමයි, ඉන්පසු එය එම විශේෂිත ඇල්ලීම් කුට්ටි තුළට අමතන්න:

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

27
සිත්ගන්නා අදහස සහ VB.net සමහර විට C # ට වඩා රසවත් වාසි ඇති බවට තවත් උදාහරණයක්
මයිකල් ස්ටම්

47
සමග @MichaelStum බව මම කිසිසේත් සියලු දී රසවත් යනුවෙන් හැඳින්විය හැකි ... කාරක රීති වගේ කම්පනයට
MarioDS

17
ව්‍යතිරේක පෙරහන් c # 6 හි පැමිණේ! Roslyn.codeplex.com/discussions/541301 නැවත පිරවීම
Arne Deruwe

LinkArneDeruwe එම සබැඳියට ස්තූතියි! මම ඉගෙනගෙන නැහැ නැවත විසි එක් වඩා වැදගත් හේතුව: throw e;විනාශ කරන stacktrace හා callstack, throw;"පමනක්" callstack A (! අනතුරකින්-ඇඟට පලක් ඉටු) විනාශ ඉතා එය වලක්වා ගැනීමට නම් හෝ යහපත් ලෙස උපයෝගී කර හේතුව!
AnorZaken

1
සී # 6 වන විට ව්‍යතිරේක පෙරහන් තිබේ! අවසාන.
ඩැනී

134

සම්පූර්ණත්වය වෙනුවෙන්, සිට .NET 4.0 කේතය ලෙස නැවත ලියා හැක:

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

ට්‍රයිපාර්ස් කිසි විටෙකත් ව්‍යතිරේකයන් විසි නොකරන අතර ආකෘතිය වැරදියි නම් අසත්‍යය ලබා දෙයි 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;

C # 12 හි පිටත පරාමිතීන් විසංයෝජනය කරන විට මෙම නිෂ් less ල පිළිතුරට ඊළඟ නිෂ් less ල යාවත්කාලීනය පැමිණේ. :)


19
හරියටම - සංක්ෂිප්තව, සහ ව්‍යතිරේකය හැසිරවීමේ කාර්ය සාධන ද penalty ුවම, වැඩසටහන් ප්‍රවාහය පාලනය කිරීම සඳහා හිතාමතාම ව්‍යතිරේක භාවිතා කිරීමේ නරක ස්වරූපය සහ ඔබේ පරිවර්තන තර්කනය වටා පැතිරීමේ මෘදු අවධානය, ඔබ මෙහි ටිකක් සහ ටිකක් .
ක්‍රේග්

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
වාව් ඔබ ප්‍රශ්නයට පිළිතුරු දී ඇත, එය ප්‍රශ්නයේ ආත්මයේ නොමැති බව හැර. වඩා විශාල ගැටළුව වෙනත් දෙයකි :(
nawfal

6
ට්‍රයිපාර්ස් භාවිතා කිරීම සඳහා සුදුසු රටාව, ඇත්ත වශයෙන්ම, වඩා සමාන ය if( Guid.TryParse(s, out guid){ /* success! */ } else { /* handle invalid s */ }, එමඟින් ආදාන අගය ඇත්ත වශයෙන්ම මාර්ගෝපදේශයක තන්තු නිරූපණය විය හැකි බිඳුණු උදාහරණය මෙන් කිසිදු අවිනිශ්චිතතාවයක් ඉතිරි නොවේ.
ක්‍රේග්

2
Guid.Parse සම්බන්ධයෙන් මෙම පිළිතුර ඇත්ත වශයෙන්ම නිවැරදි විය හැකි නමුත් මුල් ප්‍රශ්නයේ සමස්ත කරුණම එයට මග හැරී ඇත. එයට Guid.Parse සමග කිසිදු සම්බන්ධයක් නොතිබුණි, නමුත් Exception එදිරිව FormatException / OverflowException / යනාදිය අල්ලා ගැනීම සම්බන්ධයෙන් විය.
කොනර් ගැලගර්

119

ව්‍යතිරේක පෙරහන් දැන් c # 6+ හි ඇත. ඔබට කළ හැකිය

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

C # 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

ඔබේ යෙදුම C # 6 දක්වා උත්ශ්‍රේණිගත කළ හැකි නම් ඔබ වාසනාවන්තයි. නව C # අනුවාදය ව්‍යතිරේක පෙරහන් ක්‍රියාත්මක කර ඇත. එබැවින් ඔබට මෙය ලිවිය හැකිය:

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

නමුත් එය එසේ නොවේ. ඇත්ත වශයෙන්ම මෙය C # 6 හි ඇති එකම නව ලක්ෂණය වන අතර එය පෙර සංස්කරණවල අනුකරණය කළ නොහැක. පළමුව, නැවත විසි කිරීම යනු අල්ලා ගැනීම මඟ හැරීමට වඩා ඉහළින් ය. දෙවනුව, එය අර්ථාන්විතව සමාන නොවේ. ඔබ ඔබේ කේතය නිදොස්කරණය කරන විට නව අංගය තොගය නොවෙනස්ව ආරක්ෂා කරයි. මෙම අංගය නොමැතිව ක්‍රෑෂ් ඩම්ප් අඩු ප්‍රයෝජනවත් හෝ නිෂ් less ල ය.

කෝඩ්ප්ලෙක්ස් හි මේ පිළිබඳ සාකච්ඡාවක් බලන්න . හා වෙනස පිළිබඳ උදාහරණයක් .


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 XOR Catch 2 ඒ අනුව ක්‍රියාත්මක වේ):

ව්‍යතිරේක පෙරහන් MSIL

එසේම, විශේෂයෙන් Guidසතුව Guid.TryParseක්රමය.


පෙරහන් කරන විට බහු පෙන්වීම සහ බහු පෙරහන් භාවිතා කරන විට කුමක් සිදුවේද යන්න පැහැදිලි කිරීමක් සඳහා +1.
steven87vt

26

සී # 7 සමඟ ස්විච් ප්‍රකාශයක කියවීමේ හැකියාව තබා ගනිමින් මයිකල් ස්ටම්ගේ පිළිතුර වැඩිදියුණු කළ හැකිය:

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

සහ ස්විච් ප්‍රකාශනය ලෙස C # 8 සමඟ:

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

3
මෙය 2018 IMHO වන විට පිළිගත් පිළිතුර විය යුතුය.
මෙම්ෆිස්

6
මැට් ජේගේ පිළිතුර whenස්විචයකට වඩා අලංකාර / සුදුසු ය.
rgoliveira

grgoliveira: ප්‍රශ්නයේදී ඇසූ නඩුව සඳහා, මැට් ජේගේ පිළිතුර වඩාත් අලංකාර සහ සුදුසු බව මම එකඟ වෙමි. කෙසේ වෙතත්, ඔබට ව්‍යතිරේක වර්ගය අනුව ක්‍රියාත්මක කිරීමට අවශ්‍ය විවිධ කේත තිබේ නම් හෝ ව්‍යතිරේකයේ උදාහරණය සත්‍ය වශයෙන්ම භාවිතා කිරීමට අවශ්‍ය නම් කියවීම දුෂ්කර වේ. මෙම ස්විච් ප්‍රකාශය සමඟ මෙම සියලු අවස්ථා සමානව සැලකිය හැකිය.
ෆේබියන්

1
Ab ෆේබියන් "ඔබට වෙනස් කේතයක් තිබේ නම් ව්‍යතිරේක වර්ගය අනුව ක්‍රියාත්මක කිරීමට අවශ්‍ය නම් හෝ ව්‍යතිරේකයේ උදාහරණය භාවිතා කිරීමට ඔබට අවශ්‍ය නම්", එවිට ඔබ වෙනත් catchබ්ලොක් එකක් සාදයි , නැතහොත් ඔබට එය කෙසේ හෝ දැමිය යුතුය .. මගේ අත්දැකීම් අනුව, throw;ඔබේ catchකොටසෙහි ඇති කේත සුවඳක් විය හැකිය.
rgoliveira

grgoliveira: අල්ලා ගැනීමේ කොටසකට විසි කිරීම භාවිතා කිරීම අවස්ථා කිහිපයකදීම සබැඳිය බලන්න . සිද්ධි ප්‍රකාශය ඇත්ත වශයෙන්ම රටා ගැළපෙන සබැඳිය භාවිතා කරන බැවින් ඔබ ඉවතලන ක්‍රියාකරු සබැඳිය (යටි ඉරි) විචල්‍ය නාමයකින් ආදේශ කරන්නේ නම් වාත්තු කිරීම අවශ්‍ය නොවේ . මාව වැරදියට තේරුම් ගන්න එපා, ව්‍යතිරේක පෙරහන් එය කරන පිරිසිදු ක්‍රමයක් බව මම ඔබ සමඟ එකඟ වෙමි, නමුත් බහු ඇල්ලීමේ කුට්ටි මඟින් රැලි වරහන් විශාල ප්‍රමාණයක් එක් කරයි.
ෆේබියන්

20

ලොව පිළිගත් පිළිතුර CodeAnalysis / හැර, පිළිගත හැකි බව පෙනේ FxCop එය සාමාන්ය හැර වර්ගය නෙත් ඇදගන්නා වෙනවා බව ගැන පැමිණිලි කරනු ඇත.

එසේම, "is" ක්රියාකරු කාර්ය සාධනය තරමක් පිරිහීමට ලක් කළ හැකි බව පෙනේ.

CA1800: අනවශ්‍ය ලෙස වාත්තු නොකරන්න , “ඒ වෙනුවට“ ක්‍රියාකරුගේ ප්‍රති result ලය පරීක්ෂා කිරීම ගැන සලකා බලන්න ”, නමුත් ඔබ එය කරන්නේ නම්, ඔබ එක් එක් ව්‍යතිරේකය වෙන වෙනම අල්ලා ගන්නේ නම් වඩා කේතයක් ලියනු ඇත.

කෙසේ වෙතත්, මෙන්න මම කරන්නේ කුමක්ද:

bool exThrown = false;

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

if (exThrown)
{
    // Something else
}

19
නමුත් ඔබ මේ ආකාරයට කළහොත් තොග හෝඩුවාව අහිමි නොවී ව්‍යතිරේකය නැවත සලකා බැලිය නොහැකි බව මතක තබා ගන්න. (පිළිගත් පිළිතුරට මයිකල් ස්ටම්ගේ අදහස බලන්න)
රෙනේ

2
ව්‍යතිරේකය ගබඩා කිරීමෙන් මෙම රටාව වැඩිදියුණු කළ හැකිය (කරුණාකර දුර්වල හැඩතල ගැන්වීම ගැන සමාවෙන්න - අදහස් දැක්වීමේදී කේත දැමිය යුතු ආකාරය මට සිතාගත නොහැක): ව්‍යතිරේකය ex = null; උත්සාහ කරන්න {// යමක්} ඇල්ලීම (FormatException e) {ex = e; } ඇල්ලීම (OverflowException e) {ex = e; } if (ex! = null) {// වෙනත් දෙයක් සහ ex සමඟ ගනුදෙනු කරන්න}
ජෙසී වෙයිගර්ට්

3
Es ජෙසීවිගර්ට්: 1. ඔබට පෙළක් කැබැල්ලකට මොනෝ-පරතරයකින් යුත් අකුරු සහ ලා අළු පසුබිමක් ලබා දිය හැකිය. 2. ස්ටැක්ට්‍රේස් ඇතුළු මුල් ව්‍යතිරේකය නැවත සලකා බැලීමට ඔබට තවමත් නොහැකි වනු ඇත .
ඔලිවර්

2
LeCleverNeologism isක්‍රියාකරු භාවිතා කිරීම කාර්ය සාධනය කෙරෙහි සුළු negative ණාත්මක බලපෑමක් ඇති කළ හැකි බව සත්‍යයක් වුවද, ව්‍යතිරේකය හසුරුවන්නා කාර්ය සාධනය ප්‍රශස්ත කිරීම ගැන ඕනෑවට වඩා සැලකිලිමත් විය යුතු ස්ථානයක් නොවන බව සත්‍යයකි. ඔබගේ යෙදුම ව්‍යතිරේක හසුරුවන්නන් සඳහා වැඩි කාලයක් ගත කරන්නේ නම්, කාර්ය සාධන ප්‍රශස්තිකරණය යෙදුම් ක්‍රියාකාරිත්වයේ සැබෑ වෙනසක් ඇති කරයි නම්, විමසිලිමත්ව බැලීමට වෙනත් කේත ගැටළු තිබේ. එසේ පැවසීමෙන් පසු, මම තවමත් මෙම විසඳුමට කැමති නොවන්නේ ඔබට තොග හෝඩුවාව නැති වූ නිසාත්, පිරිසිදු කිරීම සන්දර්භයෙන් අල්ලා ගැනීමේ ප්‍රකාශයෙන් ඉවත් කරන නිසාත් ය.
ක්‍රේග්

3
isක්‍රියාකරු කාර්ය සාධනය පහත හෙලන එකම අවස්ථාව වන්නේ ඔබ පසුව asමෙහෙයුමක් සිදු කරන්නේ නම් (එබැවින් ඔවුන් අනවශ්‍ය ලෙස රීතිය සුදුසුකම් ලබයි ). ඔබ කරමින් සිටින්නේ වාත්තු කිරීම අවශ්‍ය නොවී වාත්තු කිරීම නම්, isක්‍රියාකරු යනු ඔබට භාවිතා කිරීමට අවශ්‍ය දේමයි.
ආචාර කරන්න

19

C # 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ව්‍යතිරේකයක් විසි නොකළ අවස්ථාවක මෙය ක්‍රියාත්මක වේ.
Sepster

4
//sepster මම හිතන්නේ "// යමක්" පසු ආපසු එන ප්‍රකාශය මෙහි ගම්‍ය වේ. මම විසඳුමට සැබවින්ම කැමති නැත, නමුත් මෙය සාකච්ඡාවේ ruc ලදායී ප්‍රභේදයකි. ඔබගේ downvote ඉවත් කිරීමට +1 :-)
toong

Ep සෙප්ස්ටර් ටූං හරි, මම හිතුවේ ඔබට නැවත එහි යාමට අවශ්‍ය නම් ඔබ එකක් දමනු ඇතැයි කියාය ... මම උත්සාහ කළේ සමාන නමුත් නිශ්චිත ප්‍රශ්න නොමැති අනෙක් අයට වාසි සැලසෙන අවස්ථාවකදී සියලු අවස්ථාවන්ට අදාළ වන පරිදි මගේ පිළිතුර සාමාන්‍ය කිරීමටයි. හොඳින්. කෙසේ වෙතත්, හොඳ මිනුමක් සඳහා, මම returnමගේ පිළිතුරට එකතු කරමි. ආදානයට ස්තූතියි.
bsara

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
}

සංස්කරණය කරන්න: මෙම පෙරණය හැර C # 6.0 දී කාරක රීති ටිකක් පිරිසිදු කිරීමට හා සමඟ එන ඇත අනෙකුත් ප්රතිලාභ සංඛ්යාව ඕනෑම වත්මන් විසඳුමක් කට. (වඩාත් කැපී පෙනෙන ලෙස තොගය නිරුපද්‍රිතව තැබීම)

C # 6.0 සින්ටැක්ස් භාවිතා කරමින් එකම ගැටළුව පෙනෙන්නේ කෙසේද යන්න මෙන්න:

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

2
+1, මෙය හොඳම පිළිතුරයි. ඉහළම පිළිතුරට වඩා එය බොහෝ දුරට හොඳ නැති නිසා returnතත්වය ප්‍රතිලෝම කිරීමද ටිකක් හොඳය.
ඩී.සී.ෂනන්

මම ඒ ගැන හිතුවේවත් නැහැ. හොඳ ඇල්ලීම, මම එය ලැයිස්තුවට එකතු කරමි.
ස්ටෙෆාන් ටී

16

Ic මිචෙල්

ඔබගේ කේතයේ තරමක් සංශෝධිත අනුවාදය:

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

නූල් සැසඳීම් කැත සහ මන්දගාමී වේ.


21
“Is” යතුර පමණක් භාවිතා නොකරන්නේ ඇයි?
ක්‍රිස් පීට්ස්මන්

29
Ic මයිකල් - මයික්‍රොසොෆ්ට් විසින් ෆෝමැට්එක්සෙප්ෂන් වෙතින් ලබාගත් StringTooLongException හඳුන්වා දුන්නේ නම්, එය තවමත් ආකෘතියේ ව්‍යතිරේකයකි, විශේෂිත එකක් පමණි. එය රඳා පවතින්නේ ඔබට 'මෙම නිශ්චිත ව්‍යතිරේක වර්ගය අල්ලා ගන්න' හෝ 'නූල්වල ආකෘතිය වැරදියි යන්නෙන් අදහස් වන ව්‍යතිරේකයන් අල්ලා ගැනීම' යන අර්ථ නිරූපණය අවශ්‍යද යන්නයි.
ග්‍රෙග් බීච්

6
Ic මයිකල් - එසේම, "ඇල්ලීම (FormatException ex) හි අවසාන අර්ථකථන ඇති බැවින් එය FormatException වෙතින් ලබාගත් ඕනෑම දෙයක් අල්ලා ගනු ඇත.
ග්‍රෙග් බීච්

14
Ex “ex” නොමැතිව ඇලෙක්ස් අංක “විසි කිරීම” මුල් ව්‍යතිරේකය, මුල් සිරස් හෝඩුවාව ඇතුළුව ඉහළට ගෙන යයි. "Ex" එකතු කිරීමෙන් තොගයේ හෝඩුවාව නැවත සැකසෙනු ඇත, එබැවින් ඔබට මුල් පිටපතට වඩා වෙනස් ව්‍යතිරේකයක් ලැබේ. මට වඩා වෙනත් කෙනෙකුට එය පැහැදිලි කළ හැකි බව මට විශ්වාසයි. :)
සමන්ත බ්‍රැන්හැම්

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 හි කළ හැකි නමුත්, vb.net හි ලියා ඇති සී එතීම භාවිතා කර C # වෙතින් ඇමතුමක් ලබා ගන්නේ නම් මිස C # හි නොවේ.
සුපර් කැට්

1
ව්‍යතිරේකයක් අල්ලා නොගෙන ක්‍රියා කරන්නේ කෙසේද? මට ඔබව සම්පූර්ණයෙන්ම තේරෙන්නේ නැත.
nawfal

@nawful ... VB පෙරනය භාවිතා කරන - කාර්යය filt මිස, (ලෙස හිටපු): උඩ හිටපු විට filt (හිටපු): පසුව උඩ පෙලට ... ආපසු බොරු: LogEx (හිටපු)
FastAl

1
#FastAl C # 6 හි ව්‍යතිරේක-පෙරහන් ඉඩ දෙන්නේ කුමක් ද?
HimBromBeere

ImHimBromBeere ඔව් ඒවා සෘජු ප්‍රතිසමයන්
FastAl

9

යාවත්කාලීන කිරීම 2015-12-15: https://stackoverflow.com/a/22864936/1718702 බලන්න C # 6 සඳහා . එය භාෂාවෙන් පිරිසිදු හා දැන් ප්‍රමිතියකි.

වඩාත් අලංකාර විසඳුමක් අවශ්‍ය පුද්ගලයින් සඳහා සන්නද්ධ වේඑක් වරක් අල්ලා ව්‍යතිරේකයන් පෙරීම මම සූදානම් කර ඇති අතර, පහත දැක්වෙන පරිදි මම දිගු කිරීමේ ක්‍රමයක් භාවිතා කරමි.

මෙම පුස්තකාලය දැනටමත් මගේ පුස්තකාලයේ ඇත, මුලින් ලියා ඇත්තේ වෙනත් අරමුණු සඳහා ය, නමුත් එය 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));
        }
    }
}

නියැදි NUnit ඒකක පරීක්ෂණ දෙකක්

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". බොහෝ ස්ථානවල මෙය ඇත්ත වශයෙන්ම නඩත්තු නිරයක් නිර්මාණය කළේය. වසර ගණනාවකට පසු, බොහෝ ක්‍රමලේඛකයින් තමන් නිර්මාණය කළ රාක්ෂයා ගැන ආඩම්බර වන්නේ නැත. එය ඔබ කියවීමට පුරුදු වී ඇති දේ නොවේ. එය "හාහ්?" බලපෑම, හෝ දරුණු "WTFs" පවා. සමහර විට එය අවුල් සහගත ය. එය කරන එකම දෙය නම් නඩත්තු කිරීමේදී පසුකාලීනව ගනුදෙනු කිරීමට අවශ්‍ය අයට කේතය ග්‍රහණය කර ගැනීම වඩා දුෂ්කර කිරීමයි - එක් ක්‍රමලේඛකයෙකු “දක්ෂ” වීමට උත්සාහ කළ නිසා පමණි. වසර ගණනාවක් තිස්සේ මම දැනගත්තා එම “දක්ෂ” විසඳුම් කලාතුරකින් හොඳ ඒවා බවත්.
කයි

1
හෝ වචන කිහිපයකින්: භාෂාව ස්වදේශීයව සපයන හැකියාවන් සමඟ බැඳී සිටින්න. භාෂාවක අර්ථ නිරූපණය අභිබවා යාමට උත්සාහ නොකරන්න, ඔබ ඒවාට අකමැති නිසා පමණි . ඔබේ සගයන් (සහ සමහර විට අනාගත-මට) ඔබට අවංකවම ස්තූතියි.
කයි

ඔබේ විසඳුම ඕනෑම අනුවාදයක whenමෙන් C # 6 හි අර්ථ නිරූපණයන් පමණක් ආසන්න වශයෙන් සලකන්න . මෙහි සැබෑ වටිනාකම නම් , ව්‍යතිරේකය අල්ලා ගැනීමට පෙර පෙරණය ක්‍රියාත්මක වන අතර එමඟින් නැවත විසි කිරීමේ වියදම / තොග දූෂණය වළක්වා ගත හැකිය. මීට පෙර VB සහ MSIL වෙත පමණක් ප්‍රවේශ විය හැකි CLR අංගයකින් එය ප්‍රයෝජන ගනී. 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
    }

අපට මෙය අවශ්‍ය වීමට හේතුව, ව්‍යතිරේක හසුරුවන්නා අපට පසුව අවශ්‍ය ක්‍රියාවලීන් අල්ලා ගැනීමට අවශ්‍ය නොවන බැවිනි. ඇත්ත වශයෙන්ම, අපට ව්‍යතිරේකයක් අල්ලාගෙන කුමක් කළ යුතු දැයි 'if' සමඟ පරීක්ෂා කළ හැකිය, නමුත් අපි අවංක වෙමු, අපට එය ඇත්තෙන්ම අවශ්‍ය නැත. (FxCop, නිදොස් කිරීමේ ගැටළු, කැත)

ඉතින් ඇයි මෙම කේතය සම්පාදනය නොකරන්නේ - සහ අපට එය හැකි ආකාරයට හැක් කළ හැක්කේ කෙසේද?

අපි කේතය දෙස බැලුවහොත්, අපි ඇත්තටම කිරීමට කැමති ඇමතුම ඉදිරියට යැවීමයි. කෙසේ වෙතත්, එම්එස් පාර්ටිෂන් II ට අනුව, අයිඑල් ව්‍යතිරේක හෑන්ඩ්ලර් බ්ලොක් මේ ආකාරයෙන් ක්‍රියා නොකරනු ඇත, මේ අවස්ථාවේ දී එය අර්ථවත් වන්නේ 'ව්‍යතිරේක' වස්තුවට විවිධ වර්ග තිබිය හැකි බැවිනි.

නැතහොත් එය කේතයෙන් ලිවීමට, අපි සම්පාදකයාගෙන් මේ වගේ දෙයක් කරන්නැයි ඉල්ලා සිටිමු (හොඳයි එය සම්පූර්ණයෙන්ම නිවැරදි නොවේ, නමුත් එය මා අනුමාන කළ හැකි ආසන්නතම දෙයයි):

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

මෙය සම්පාදනය නොකිරීමට හේතුව පැහැදිලිය: '$ ව්‍යතිරේකය' වස්තුව සතුව ඇති වර්ගය සහ වටිනාකම (මෙහි 'ඊ' විචල්‍යයන්හි ගබඩා කර ඇත)? මෙය හැසිරවීමට අපට අවශ්‍ය ක්‍රමය නම්, ව්‍යතිරේක දෙකෙහිම පොදු පාදක වර්ගය 'ව්‍යතිරේකය' බව සටහන් කර ගැනීම, විචල්‍යයක් සඳහා ව්‍යතිරේක දෙකම අඩංගු වන ලෙස භාවිතා කරන්න, ඉන්පසු හසු වූ ව්‍යතිරේක දෙක පමණක් හැසිරවීම. IL හි මෙය ක්‍රියාත්මක කරන ආකාරය VB.Net හි ඇති 'පෙරණය' ලෙස දැක්විය හැකිය.

එය C # හි වැඩ කිරීමට නම්, අපට නිවැරදි 'ව්‍යතිරේක' පාදක වර්ගය සහිත තාවකාලික විචල්‍යයක් අවශ්‍ය වේ. කේතයේ ප්රවාහය පාලනය කිරීම සඳහා, අපට ශාඛා කිහිපයක් එකතු කළ හැකිය. මෙන්න:

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

එය 'නැවත විසි කිරීම' අතහැර දමයි. මෙය ක්‍රියාත්මක වීමට නම්, 'ඇල්ලීමේ' කොටස තුළ හැසිරවීම සිදු කිරීමට අපට හැකි විය යුතුය - මෙම කාර්යය කිරීමට ඇති එකම ක්‍රමය අල්ලා ගැනීමේ 'ව්‍යතිරේක' වස්තුවකි.

මෙම අවස්ථාවෙහිදී, අධි බර විභේදනය භාවිතා කරමින් විවිධ ආකාරයේ ව්‍යතිරේකයන් හසුරුවන වෙනම ශ්‍රිතයක් අපට එකතු කළ හැකිය, නැතහොත් ව්‍යතිරේකය හැසිරවිය හැකිය. දෙදෙනාම අවාසි ඇත. ආරම්භ කිරීමට, සහායක ශ්‍රිතයක් සමඟ එය කළ හැකි ආකාරය මෙන්න:

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

මෙය සෑම C # සංවර්ධකයෙක්ම අවසානයේ මුහුණ දෙන සම්භාව්‍ය ගැටලුවකි.

ඔබේ ප්‍රශ්නය ප්‍රශ්න 2 කට බෙදීමට මට ඉඩ දෙන්න. පළමු,

මට එකවර බහුවිධ ව්‍යතිරේකයන් අල්ලා ගත හැකිද?

කෙටියෙන් කිවහොත් නැත.

එය ඊළඟ ප්‍රශ්නයට තුඩු දෙයි,

එකම ඇල්ලීමේ () වාරණයක දී මට ව්‍යතිරේක වර්ග කිහිපයක් අල්ලා ගත නොහැකි බැවින් අනුපිටපත් කේත ලිවීමෙන් වැළකී සිටින්නේ කෙසේද?

ඔබේ නිශ්චිත නියැදිය අනුව, පසුබෑමේ අගය ඉදිකිරීමට ලාභදායී වන විට, මම මෙම පියවර අනුගමනය කිරීමට කැමතියි:

  1. පසුබෑමට ලක්වන අගයට WebId ආරම්භ කරන්න.
  2. තාවකාලික විචල්‍යයකින් නව මාර්ගෝපදේශයක් සාදන්න.
  3. WebId සම්පුර්ණයෙන්ම සාදන ලද තාවකාලික විචල්‍යයට සකසන්න. මෙය උත්සාහ කරන්න {} වාරණයේ අවසාන ප්‍රකාශය කරන්න.

එබැවින් කේතය පෙනේ:

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 කිසි විටෙකත් අඩක් සාදන ලද අගයට සකසා නැති අතර එය මඟ පෙන්වීමක් ලෙස පවතී.

පහත වැටීමේ අගය තැනීම මිල අධික නම් සහ වටිනාකමක් නැවත සැකසීම වඩා ලාභදායී නම්, මම නැවත සැකසීමේ කේතය එහි ශ්‍රිතයට ගෙන යන්නෙමි:

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

මෙය කදිමයි, “පාරිසරික කේතීකරණය” එනම් ඔබ ඔබේ කේතය සහ දත්ත අඩිපාර ගැන ඉදිරියෙන් සිතන අතර අඩක් සැකසූ අගයන් කාන්දු නොවන බවට වග බලා ගන්න. මෙම රටාව අනුගමනය කිරීම සතුටක් ජෙෆ්රි!
තාහීර් කාලිඩ්

6

ඉතින් ඔබ සෑම ව්‍යතිරේක-ස්විචයක් තුළම කේත ගොඩක් පුනරාවර්තනය කරනවාද? ක්‍රමයක් උපුටා ගැනීම දෙවියන්ගේ අදහසක් වනු ඇත, එසේ නොවේ ද?

එබැවින් ඔබේ කේතය මෙයට පැමිණේ:

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

දැනටමත් දිගු මෙම ත්‍රෙඩ් එකට මගේ කෙටි පිළිතුර එක් කිරීමට අවශ්‍ය විය. සඳහන් කර නැති දෙයක් නම්, අල්ලා ගැනීමේ ප්‍රකාශවල ප්‍රමුඛතාවයේ අනුපිළිවෙලයි, වඩාත් නිශ්චිතවම ඔබ අල්ලා ගැනීමට උත්සාහ කරන එක් එක් වර්ගයේ ව්‍යතිරේකයේ විෂය පථය පිළිබඳව ඔබ දැනුවත් විය යුතුය.

උදාහරණයක් ලෙස ඔබ "උඩ-සියලු" හැර ලෙස භාවිතා කරන්නේ නම් ව්යතිරේක විරෝධී රටාව මම හිතන්නේ එය අනෙකුත් සියලු උඩ ප්රකාශ 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 ලේඛනය සමාලෝචනය කිරීමට මම තරයේ නිර්දේශ කරමි:

ව්‍යතිරේක ධූරාවලිය


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 ඩබ්ලිව්ටීඑෆ් :-) මෙය පිළිතුරක් ලෙස සලකුණු නොකළ යුතුව තිබුනි, නමුත් එය ඔහු භයානක ය.
ආරොන්

1
අපට එය කෙතරම් සරලව කළ හැකිද යන්න ගැටළුවක් නොවේ. නමුත් ඔහු නිකම් ඉඳගෙන එය විසඳීමට ඔහුගේ අදහස ඉදිරිපත් කළේ නැත. ඇත්තටම අගය.
මැක්සිමස්

2
ඇත්ත වශයෙන්ම මෙය සිදු නොකරන්න, C # 6 හි ව්‍යතිරේක පෙරහන් හෝ වෙනත් පිළිතුරු භාවිතා කරන්න - මම මෙය මෙහි විශේෂයෙන් සඳහන් කළේ "මෙය එක් ක්‍රමයක්, නමුත් එය නරකයි, මට වඩා හොඳ දෙයක් කිරීමට අවශ්‍යයි" යනුවෙනි.
මයිකල් ස්ටම්

මෙය නරක ඇයි? ස්විච් ප්‍රකාශයක ව්‍යතිරේකය කෙලින්ම භාවිතා කළ නොහැකි බව මට ප්‍රහේලිකාවක් විය.
MKesper

3
@MKesper එය නරක වීමට හේතු කිහිපයක් මම දකිමි. සම්පුර්ණ සුදුසුකම් ලත් පංති නාම වචන වචනාර්ථයෙන් ලිවීම අවශ්‍ය වන අතර එය සම්පාදකයාට ඔබව ගලවා ගත නොහැකි යතුරු ලියනයන්ට ගොදුරු වේ. එසේම එය වන ව්යතිරේකයක් ගැලපෙන අසාර්ථක වනු ඇත (බොහෝ කඩ සාප්පු දෝෂයක් අවස්ථාවල දී අඩු හොඳින් පරීක්ෂා, ඒවා එසේ සුළු වැරදි වැඩි මග කිරීමට නියමිතය. පසුව මෙම සැලකිය යුතු මිල) උපපංතිය නිශ්චිත නඩු එක්. තවද, නූල් වීම නිසා, වීඑස් හි “සියලු යොමු සොයාගන්න” වැනි මෙවලම් මඟින් නඩු මඟ හැරෙනු ඇත - විශේෂිත ව්‍යතිරේකයක් හසු වූ සෑම තැනකම පිරිසිදු කිරීමේ පියවරක් එක් කිරීමට ඔබට අවශ්‍ය නම් අදාළ වේ.
මාර්ක් අමරි

2

මෙහි සඳහන් කිරීම වටී. ඔබට බහු සංයෝජන වලට ප්‍රතිචාර දැක්විය හැකිය (ව්‍යතිරේක දෝෂය සහ ව්‍යතිරේකය.

පාලක වස්තුව ඩේටාග්‍රිඩ් එකක වාත්තු කිරීමට උත්සාහ කරන විට, ටෙක්ස්ට් බොක්ස්, ටෙක්ස්ට් බ්ලොක් හෝ චෙක්බොක්ස් වැනි අන්තර්ගතයන් සමඟ මම භාවිත අවස්ථාවකට මුහුණ දුන්නෙමි. මෙම අවස්ථාවේ දී ආපසු ලබා දුන් ව්‍යතිරේකය සමාන වූ නමුත් පණිවිඩය වෙනස් විය.

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

මේ සඳහා ඔබ System.Action ට සමාන "Catch" ක්‍රමයේ අධි බර කිහිපයක් සෑදිය යුතුය.

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

ඔබ කැමති තරම් ගණනක් එසේ කරන්න. නමුත් ඔබ එය එක් වරක් කළ යුතු අතර ඔබට එය ඔබගේ සියලු ව්‍යාපෘති වල භාවිතා කළ හැකිය (නැතහොත්, ඔබ නූගට් පැකේජයක් නිර්මාණය කළේ නම් අපට එයද භාවිතා කළ හැකිය).

සහ CatchMany ක්‍රියාත්මක කිරීම:

    [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
um. මෙය ප්‍රශ්නයේ අරමුණ පරාජය කිරීමයි. ඔහු මෙම ප්‍රශ්නය අසන්නේ අනුපිටපත් කේතයෙන් මිදීමටය. මෙම පිළිතුර තවත් අනුපිටපත් කේතයක් එක් කරයි.
ජේම්ස් ඊෂ්

-23

C # 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
මෙම උදාහරණයෙන් ව්‍යතිරේක පෙරහන් භාවිතා කිරීමක් නොපෙන්වයි.
user247702

C # 6.0 හි ව්‍යතිරේකය පෙරීම සඳහා මෙය සම්මත ක්‍රමයකි
කෂිෆ්

5
ව්‍යතිරේක පෙරහන් යනු කුමක්දැයි නැවත බලන්න. ඔබ ඔබේ උදාහරණයේ ව්‍යතිරේක පෙරණයක් භාවිතා නොකරයි. ඔබේ පිළිතුරට වසරකට පෙර පළ කරන ලද මෙම පිළිතුරෙහි සුදුසු උදාහරණයක් තිබේ .
user247702

6
ව්‍යතිරේක පෙරීම සඳහා උදාහරණයක් වනුයේcatch (HttpException e) when e.GetHttpCode() == 400 { WriteLine("Bad Request"; }
ආචාර කරන්න
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.