アツログ

つけめんは、ひやもり派のあつもりです。ガジェットだったり、食だったり、プログラミングだったりの趣味記事をあげていきます

アツログ

【C#】try-catch-finallyの中にreturnを書いた場合の動きが予想外だった件

あとで読む

f:id:AshG:20170912113859j:plain

今朝目覚めたときに、向かいのお宅からラジオ体操が聞こえ、昔を思い出してセンチメンタルになりました。

みなさん、おはこんばちは。あつもりです。

今回は、プログラミングのお話です。

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はどこまでもふぁいなりーなのであった。

文字配列を文字列に変換する方法もよく忘れるので、ちらっと上記コードに書いてみた。

ひとこと

こうして記事に書き起こすことで、復習になるなぁと思う働きたくないでござるマンでした。

諸行無常だね。