【C#】try-catch-finallyの中にreturnを書いた場合の動きが予想外だった件
今朝目覚めたときに、向かいのお宅からラジオ体操が聞こえ、昔を思い出してセンチメンタルになりました。
みなさん、おはこんばちは。あつもりです。
今回は、プログラミングのお話です。
finallyがどこまでもふぁいなりーとは思わなかった。
【C#】try-catch-finallyの中にreturnを書いた場合の動き
まずは、おさらいから。
おさらいなんていらねぇ!!結論を知りてぇんだ!!という方は、ここをクリック!!!
【おさらい】try-catchの動き
なんのために、try-catchがあるのかというと、例外をハンドリングするためです。
例えば、以下のコードの場合、nullオブジェクトのaをint型にキャストしようとする部分で、NullReferenceExceptionが発生します。
static void Main(string[] args) { object a = null; int b = (int)a; }
この例外をハンドリグするために、必要になるのがtry-catch
例外が起きそうな箇所や、特定の条件の場合に例外を発生させたい場合は、try-catchで囲いましょう。
【おさらい】finallyの動き
finally句内に記述された処理は、Exceptionが起きようが、起きまいが必ず実施されます。
char[] buffer = new char[10];
int index = 0; string path = @"c:\users\public\test.txt"; StreamReader file = new StreamReader(path); try { file.ReadBlock(buffer, index, buffer.Length); } catch (Exception ex) { Console.WriteLine("Error reading from {0}. Message = {1}", path, ex.Message); } finally { if (file != null) { file.Close(); } }
test.txtから10文字読み込むコードですが、finallyが記述されていない場合には、test.txtのリソースが解放されません。
catchに書けばいいじゃんとなるかもしれませんが、その場合には、例外が発生したときにしかリソース解放が走りません。
finally句内に記述することで、例外の有無に関わらずリソース解放が走るようになります。
【おさらい】returnの動き
returnは読んで字のごとく、メソッドの呼び出し元に処理を返すものです。
計算処理をメソッド化させて、結果を返したりするときにつかったりしますね。
static void Main(string[] args) { int a = 1; int b = CalculateTwice(a); Console.Write(b); } static int CalculateTwice(int r) { int area = r * 2; return area; }
表示される結果は2
【本題】try-catch-finallyの中にreturn
さて、本題
絶対に実行されるfinallyと、絶対に呼び出し元に処理が遷移するreturn
このふたつが相対したとき、どうなるのか!!!(ほこたて風
static void Main(string[] args) { int a = 0; readFile(a); Console.WriteLine("main"); } static void readFile(int index) { char[] buffer = new char[10]; string str; string path = @"C:\Users\Public\test.txt"; StreamReader file = new StreamReader(path); try { file.ReadBlock(buffer, index, buffer.Length); str = new String(buffer); if (str.Equals("gegegagagi")) { Console.WriteLine("return"); return; } Console.WriteLine("no return"); } catch (Exception ex) { Console.WriteLine("Error reading from {0}. Message = {1}", path, ex.Message); } finally { if (file != null) { file.Close(); } Console.WriteLine("finally"); } }
test.txtの中身は"gegegagagi"の場合、コンソールに表示されるのは
return
finally
main
finallyが実行されてからreturnするんです。
これを知らなくて、finally内に、returnされない場合に割り振られるリソースのクリア処理を入れてたんだけど、Exceptionが出て悩んでた。
finallyはどこまでもふぁいなりーなのであった。
文字配列を文字列に変換する方法もよく忘れるので、ちらっと上記コードに書いてみた。
ひとこと
こうして記事に書き起こすことで、復習になるなぁと思う働きたくないでござるマンでした。
諸行無常だね。