Якая мэта «нарэшце» у Try/ўлове/нарэшце

Сінтаксіс зменіцца з адной мовы на іншую, але гэта агульнае пытанне.

У чым розніца паміж гэтым ....

try
{
     Console.WriteLine("Executing the try statement.");
     throw new NullReferenceException();
}
catch (NullReferenceException e)
{
     Console.WriteLine("{0} Caught exception #1.", e);
}       
finally
{
     Console.WriteLine("Executing finally block.");
}

і гэта....

try
{
    Console.WriteLine("Executing the try statement.");
    throw new NullReferenceException();
}
catch (NullReferenceException e)
{
    Console.WriteLine("{0} Caught exception #1.", e);
}        
Console.WriteLine("Executing finally block.");

Я працягваю бачыць гэта выкарыстоўваецца, таму я мяркую, што ёсць добрая нагода выкарыстоўваць, нарэшце, але я не магу зразумець, як гэта не адрозніваецца ад проста пакласці код пасля заявы, так як ён усё роўна будзе працаваць.

Ёсць ці калі-небудзь сцэнар, у якім, нарэшце, не працуе?

16
..which магчымы дублікат stackoverflow.com/questions/3216046/… , які з'яўляецца магчымым дублікатам stackoverflow.com/questions/ 345091/& hellip; , які мае лепшы адказ на гэтае пытанне. Ну, добры, салодкі і кароткі.
дададзена аўтар Mathieu Guindon, крыніца
дададзена аўтар epascarello, крыніца

10 адказы

У вашым прыкладзе, гэта не робіць цэлую вялікую розніцу.

Адлюструеце гэта, хоць:

    try
    {
        Console.WriteLine("Executing the try statement.");
        throw new NullReferenceException();
    }
    catch (SomeOtherException e)
    {
        Console.WriteLine("{0} Caught exception #1.", e);
    }       
    finally
    {
        Console.WriteLine("Executing finally block.");
    }

    Console.WriteLine("Executing stuff after try/catch/finally.");

У гэтым выпадку ўлоў не будзе лавіць памылку, так што ўсе, пасля таго, як усе спробы/злавіць/нарэшце, ніколі не будзе дасягнута. Тым не менш, канчаткова блок будзе па-ранейшаму працаваць .

24
дададзена
Або, калі няма ніякага падвоху блока. Тады, калі код ўнутры блока Ьги выдае памылку, выключэнне будзе атрымаць размножвае стэк ў выклікалай праграму, якая будзе апрацоўвацца дзесьці ў стэку, ці разглядаецца як неапрацаванае выключэнне. Але код у блоку, нарэшце, усё роўна будзе працаваць.
дададзена аўтар Charles Bretana, крыніца
@Maxx: Гэта больш апрацоўваць выпадкі, калі вы ў канчатковым выніку з выключэннямі, якія не былі ўлічаныя. <�Код>, нарэшце, будзе ў канчатковым выніку працуе незалежна ад таго, як вы выходзіце з TRY/злавіць, нават калі гэта з-за памылкі, вы не ведаеце, што можа здарыцца. Такім чынам, гэта лепшае месца, каб змясціць код ачысткі і такія.
дададзена аўтар cHao, крыніца
Або, калі вы паўторна выдаць выключэнне пасля некаторай памылкі толькі ачысткі. Або ў прынцыпе любы іншы час вы можаце пакінуць блок з дапамогай выключэння. У тых выпадках, кода пасля блока не будзе працаваць. Вось дзе , нарэшце, прыходзіць.
дададзена аўтар cHao, крыніца
Ах, што робіць шмат сэнсу. Дзякуй.
дададзена аўтар Maxx, крыніца
Пацешна, ня, я ніколі не бачыў, як гэта выкарыстоўваецца ў спалучэнні з кідком. Я думаю, гэта проста добрая практыка.
дададзена аўтар Maxx, крыніца
try
{
    throw new Exception("Error!");
}
catch (Exception ex)
{
    throw new Exception(ex, "Rethrowing!");
}
finally
{
   //Will still run even through the catch kicked us out of the procedure
}

Console.WriteLine("Doesn't execute anymore because catch threw exception");
8
дададзена

Гэта сапраўды залежыць ад таго - некаторыя іншыя адказы вельмі важкія прычыны, каб выкарыстоўваць Нарэшце блок. Але я думаю, што лепшая прычына ў тым, што вы робіце апрацоўка выключэнняў . Тое, што вы робіце ў Нарэшце блок звычайна ўключае ачыстку рэсурсаў для забеспячэння належнага працягу, незалежна ад таго, ці быў ці не кінута выключэнне - для мяне гэта яшчэ частка за выключэннем апрацоўкі , па меншай меры частка «паспрабаваць нешта» аперацыі.

ІМХО Нарэшце сфера падкрэслівае той факт, што яго код змяшчае матэрыял, які заслугоўвае асаблівай увагі ў выпадку выключэння.

4
дададзена

нарэшце, блок гарантавана будзе excuted. Такім чынам, у вашым прыкладзе, вынікі абодвух выпадках выглядае ж. але калі вы выкарыстоўваеце вяртанне або закінуць у блоку ўлову, вы можаце ўбачыць, што розніца.

3
дададзена

<�Моцны> Нарэшце варта выкарыстоўваць усе, што павінна быць зроблена для таго, каб захаваць сістэму паслядоўнай. Гэта звычайна азначае, вызваліць рэсурсы

Нарэшце не заўсёды выконваецца, незалежна ад таго, што было кінута выключэнне. Яго варта выкарыстоўваць для вызвалення рэсурсаў, у наступных выпадках:

  • Дапрацоўка злучэння
  • Зачыніце апрацоўшчык файлаў
  • Свабодная памяць
  • Зачыніць злучэнне з базай дадзеных

Дазвольце мне даць поўны прыклад. Уявіце сабе, што, што вы адпраўляеце паведамленні праз сетку. У псевдокоде:

// With finally                  |  //Without finally
try{                             |  try{  
  send_message()                 |    send_message() 
} catch(NetworkError){           |  } catch(NetworkError){ 
  deal_with_exception()          |    deal_with_exception()
} finally {                      |  }
  finalizes_connection()         |  finalizes_connection() 
}                                |

Адзінае адрозненне абодвух кодаў, калі тое, што трымаць у паспрабаваць блок выклікае выключэнне, якое не NetworkError , напрыклад, MethodNotFound . У першым выпадку, метад finalizes_connection() будзе называцца, а ў другім, ён не будзе.

Злучэнне, натуральна, ажыццяўляецца праз больш чым адной праграмы. Дык што ж адбываецца ў выпадку MethodNotFound выключэння ў іншай праграме? У першым выпадку, праграма завершыць злучэнне і іншую праграму, і яна будзе шчаслівая. У другім выпадку, іншая праграма можа чакаць вашага адказу назаўжды. Што рабіць, калі іншая праграма можа атрымаць толькі адно злучэнне на час? Вы проста праслухоўваюць іншую праграму, а таксама.

Гэта будзе таксама прымяняцца для файла, напрыклад, што вы адкрылі і іншыя праграмы не змогуць адкрыць для чытання (у Windows). І на памяць, ён ніколі не выпускалася, і зараз у вас ёсць ўцечка памяці.

1
дададзена

нарэшце, бяжыць як паспрабаваць злавіць. Гэта гарантуе, што ён будзе працаваць, але гэта не 100% гарантыя, што будзе [некаторыя памылкі спыніць выкананне кода]

0
дададзена
Але гэта не было б так проста змясціць яго па-за блока прымеркі злавіць?
дададзена аўтар Qantas 94 Heavy, крыніца
шмат разоў ўлоў будзе паўторна кідаць памылкі або спыніць выкананне ў, у гэтым выпадку ўсё роўна будзе працаваць код у рэшце рэшт, але код пасля блока спробы злавіць не будзе.
дададзена аўтар mconlin, крыніца
Так, але так жа любы код пасля заявы, ці не так?
дададзена аўтар Maxx, крыніца

Я не ведаю, C#, але мэта ў , нарэшце, блок у Java-МОГ мовах з'яўляецца забеспячэнне сістэмы рэсурсаў адчужаных, асабліва калі вываз смецця нерэгулярна. Гэта той жа прынцып для ўсіх. разгледзім блок

InputStream is = new FileInputStream("foo.txt");
OutputStream os = new FileOutputStream("D:/nonexistent/directory/bar.txt");
// Throws a FileNotFoundException.

Пераменная гэта створаны паспяхова, і займае сістэмныя рэсурсы. Працэсы могуць выкарыстоўваць толькі фіксаванае колькасць дэскрыптараў файлаў адначасова. Пераменная АС не ствараецца, а выключэнне, і бурбалкі да абанента. У працэсе гэта выходзіць з вобласці бачнасці, і атрымлівае права на збор смецця.

Аднак калекцыі смецця ніколі не гарантавана адбудзецца, або яны могуць адбыцца ў нявызначаны час у будучыні. Такім чынам, сістэмныя рэсурсы, прынятыя гэта не можа быць вызвалены. Гэта можа быць дарагім, ці можа прывесці да збою праграмы, калі гэта адбудзецца дастатковую колькасць разоў. Такім чынам, , нарэшце, блокі былі ўведзены ў Java. Іншыя мовы маюць падобныя канструкцыі. У C ++ дэструктары выклікаюцца дэтэрмінавана. Lispy мовах існуе раскруціцца-абароны , але тыя, як правіла, пакуюцца ў з-абуўшы макрасы.

У Java 6 і ніжэй, можна было б зрабіць гэта:

try {
    is = new FileInputStream("foo.txt");
    os = new FileOutputStream("D:/nonexistent/directory/bar.txt");
   //work...
} finally {
    if (is != null) {
        try {
            is.close();
        } catch (IOException ignored) {}
    }
    if (os != null) {
        try {
            os.close();
        } catch (IOException ignored) {}
    } 
}

Вы не можаце проста патэлефанаваць is.close() , таму што можа кінуць, а затым АС ніколі не будзе зачынена. Вы павінны праверыць NULL таксама. Разважныя людзі выкарыстоўвалі Jakarta Commons-Іа IOUtils.closeQuietly() Спосабы замяніць блок:

} finally {
    IOUtils.closeQuietly(is);
    IOUtils.closeQuietly(os);
}

Але Java 7 прадставіў лепшае рашэнне: паспрабуйце-з-рэсурсамі. C# 4, верагодна, прыйшоў першым з чымсьці падобным, Microsoft будучы хутчэй цяміць, чым Snoracle.

try (
    is = new FileInputStream("foo.txt"),
    os = new FileOutputStream("D:/nonexistent/directory/bar.txt")
) {
   //work...
}
0
дададзена
C # мае , выкарыстоўваючы , які робіць прыкладна тое ж самае з рэалізацыямі IDisposable (інтэрфейс у .net, які ўяўляе класы, якія трымаюць іншыя, чым RAM родныя рэсурсы). <�Код>, выкарыстоўваючы (вар г = новы SomeNativeResource ()) {/ * рабіць рэчы з г; * /} у значнай ступені перакладае Var R = новы SomeNativeResource (); паспрабуйце {/ * рабіць рэчы з г; * /} Нарэшце {калі (! Г = нуль) r.Dispose (); } . Гэта было вакол з ... 1.1 або больш раннімі версіямі? ... MSDN ёсць старонка для гэтага для VS 2003 г., па меншай меры.
дададзена аўтар cHao, крыніца
Да ... , нарэшце, блокі ў C# не зусім так часта, як у Java. <�Код> выкарыстоўваючы ахоплівае як 80% выпадкаў выкарыстання.
дададзена аўтар cHao, крыніца
Зыходнае паведамленне было заяўлена як радавое. Я мяркую, вам тады трэба нарэшце блокі ў C#, калі ёсць рэчы, якія вы павінны зрабіць, што вы не можаце перавесці ў IDisposable . Гэта, верагодна, рэдка.
дададзена аўтар Eric Jablow, крыніца

паспрабуйце мае патрэбу ў блоку, па меншай меры адзін захоп або finally.after выканання ўсіх ўловаў блокаў канчаткова блок будзе executed.You можа дадаць любую логіку вам трэба там што павінна быць зроблена ў канчатковым рахунку.

0
дададзена

Яго добрая практыка, каб выкарыстаць, нарэшце, для апрацоўкі збояў праграмы. нарэшце, заўсёды будзе працаваць .Калі функцыя выходзіць ўнутры блока спробы злавіць ці іншую памылку выкідваецца альбо ў спробе або ўлову, то ў рэшце рэшт усё роўна будзе выконваць. Вы не атрымаеце, што функцыянальнасць не выкарыстоўваецца, нарэшце, заяву.

0
дададзена

нарэшце, заўсёды заўсёды працуе. нарэшце, як лавец, які ніколі не прапускае нічога. У гэтым прыкладзе вы казалі, ды, нарэшце, аленевая скура дадаць любую значэнне. Але ў рэшце рэшт, як правіла, выкарыстоўваецца для ўтылізацыі/вызвалення рэсурсаў.

0
дададзена