より良いエンジニアを目指して

1日1つ。良くなる!上手くなる!

throw exとthrowは全くの別物

throw exだけど、throwに出来るの知ってる

前職の同僚に言われたことです。

   private static void test() {
        try {
            child1();
        } catch(Exception ex) {
            Console.WriteLine("例外発生:test");
            throw;
        }
    }

例外を捕捉して、throwするとき、throw; とだけ書いても捕捉した例外をthrow出来るのです。

これは知っていたのですが、

   private static void test1() {
        try {
            child1();
        } catch(Exception ex) {
            Console.WriteLine("例外発生:test1");
            throw ex;
        }
    }

というようにthrow ex;throw; と書くのは別物です。

StackTraceが追えるかの違いがあるのです。

using System;
                    
public class Program
{
    
    public static void Main()
    {
        try {
            test();
        } catch(Exception ex) {
            Console.WriteLine(ex);
        }
        try {
            test1();
        } catch(Exception ex) {
            Console.WriteLine(ex);
        }
    }
    
    private static void test() {
        try {
            child1();
        } catch(Exception) {
            Console.WriteLine("例外発生:test");
            throw;
        }
    }
    private static void test1() {
        try {
            child1();
        } catch(Exception ex) {
            Console.WriteLine("例外発生:test1");
            throw ex;
        }
    }

    private static void child1() {
        child2();
    }
    private static void child2() {
        child3();
    }
    private static void child3() {
        int a = 10;
        int b = 0;
        Console.WriteLine(a/b);
    }
}

上記のようなコードにした場合、結果は以下のようになります

例外発生:test

System.DivideByZeroException: Attempted to divide by zero.

at Program.child3() in d:\Windows\Temp\po0y23rl.0.cs:line 46

at Program.child2() in d:\Windows\Temp\po0y23rl.0.cs:line 41

at Program.child1() in d:\Windows\Temp\po0y23rl.0.cs:line 38

at Program.test() in d:\Windows\Temp\po0y23rl.0.cs:line 25

at Program.Main() in d:\Windows\Temp\po0y23rl.0.cs:line 9


例外発生:test1

System.DivideByZeroException: Attempted to divide by zero.

at Program.test1() in d:\Windows\Temp\po0y23rl.0.cs:line 33

at Program.Main() in d:\Windows\Temp\po0y23rl.0.cs:line 14

test関数の時、throw;しており、10/0の計算が発生した箇所までStackTraceが追えます。

しかし、test1関数の時、throw ex;している場合は、10/0の計算した箇所まで追えません。test1関数までです。

というわけで、全然別物です。

使いこなせないと痛手になります。

理由がない限り、throw;を使うことになるかと。

C#歴は長いのですが、知りませんでした。

動くだけのコードを書くための初歩的な情報はいくらでも転がってますが、こうした例外処理は自分で勉強していかないといけませんね。