【C# 6.0】例外狀況篩選條件(取特定例外)

介紹C# 6.0新功能-「例外狀況篩選條件」(exception filters)介紹,將會敘述如何使用這方變得的語法糖。
C# 6.0發表時間:2015年7月,始於.NET Framework 4.6,Visual Studio 2015。

這個功能是用在try...catch...中。一般時候catch中的條件,是只有抓到指定錯誤才會執行,但是現在有例外的篩選條件可以增加更多條件,以進行各種例外發生時的處理。

在catch的變數後面,增加個:when + (條件),也就是變成when (XXX),當when的條件滿足時將會動作後續的作業,如果不是的話就會忽略,繼續下一步。也就是說在catch條件中滿足了例外回傳型別,但是還有「附加條件」也就是「if」條件概念,當兩者都是為true的時候,就會執行動作。

例如:

catch (System.Net.Http.HttpRequestException e) when (e.Message.Contains("301"))
{
    Console.WriteLine("Error");
}

當發生(HttpRequestException e)的例外時,他的e(也就是型別為HttpRequestException的個體)的錯誤訊息內文要包含「301」,才會執行Console.WriteLine("Error")這一句。如果不是的話就離開,跟if一模一樣。

 

  • 而仿效微軟的範例:
using System;

public class Program
{
    public static void Main()
    {
        try 
        {
            string s = null;
            Console.WriteLine(s.Length);

        } catch (Exception e) when (LogException(e))
        {
            Console.WriteLine("e:"+e.Message);
            Console.WriteLine("Test");
        }
        catch(Exception e)
        {
            Console.WriteLine("Test:"+e.Message);
        }
        Console.WriteLine("Exception must have been handled");
    }

    private static bool LogException(Exception e)
    {
        Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}");
        Console.WriteLine($"\tMessage: {e.Message}");
        return true;
    }
}

顯示結果為:

	In the log routine. Caught System.NullReferenceException
	Message: Object reference not set to an instance of an object.
e:Object reference not set to an instance of an object.
Test
Exception must have been handled

說明:

範例中,我們定義了一個stringNULL,而後面又執行Length,會造成因為是空值而無法執行長度計算之功能,這時就可能發生例外事件。這邊是使用萬用的Exception去接這個事件。如果沒有when,就直接執行大括號({})內的行為,如同最後一個catch(Exception e),就必定執行。當在後面增加when,而我這邊會執行(LogException(e))這個功能,而他的回傳值型態bool。而在目前範例中是回傳true,也就是會執行這個exception動作,因此會印出錯誤訊息。然後這個執行完就會執行下一個exception。所以看output,可以看得出來先執行(LogException(e)),接著是該exception內的動作,最後才是另一個exception動作。其中因為例外已經被前一個exception取走,所以第二個(Exception e)會是空值。

因此動作就會是:

(LogException(e)) → 該exception內的動作 → 另一個exception動作(沒有資料)

 

如果把LogException的回傳值改成false會變成怎樣呢?就會執行(LogException(e))內的動作,因為回傳值是false,因此不會執行該exception內的動作,也沒有取出這個例外資料。而後面exception是萬用,所以也是被攔截到,而沒有when條件,所以直接執行內部的作業。

所以動作會變成:

(LogException(e)) → (不動作) → 另一個exception動作(有資料)

因此有這樣的差異,在寫例外處理的時候要特別注意。

 


結論:

  • 例外處理可以增加when的條件,就如同if判斷式一樣,如果條件是true就執行。
  • exception如果已經被前面的catch取得的話,後面就不會有例外的資料了。

參考資料:

~Copyright by Eyelash500~

技術文章:EY*研究院
iT邦幫忙:eyelash*睫毛
Blog:睫毛*Relax
Facebook:睫毛*Relax