這個做法在對做法 49 的 Exception Filters 進行補充以及它的特性。
下面這段程式碼 ConsoleLogException
會將 Exception 相關的訊息輸出到 Console 上面,並且注意到最後一行只會回傳 false,
所以使用上就可以透過 when 子句會先對條件進行檢查的特性,來做到安插監控程式碼的功能。
也就是說 ConsoleLogException(e) 這段程式碼在錯誤攔截的時候一定會優先運行,但結果又只會回傳 false 所以不會對結果有任何影響, 所以就很適合拿來寫一些日誌相關的程式碼。
void Main()
{
try
{
data = MakeWebRequest();
}
catch (Exception e) when (ConsoleLogException(e)) { }
catch (TimeoutException e) when (failures++ < 10)
{
Console.WriteLine("Timeout error: trying again");
}
}
public static bool ConsoleLogException(Exception e)
{
var oldColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Error: {0}", e);
Console.ForegroundColor = oldColor;
return false;
}
需要注意這種寫法一定要確保回傳的值為 false 絕對不可以是 true 否則錯誤檢查就會停止了,所以我們可以把
catch (Exception e) when (ConsoleLogException(e))
這段程式碼放在第一個優先檢查的 catch,
就能在任何想要進行輸出檢查的地方進行檢查,同時又不會造成任何影響。
還有另一種放在最後檢查的寫法,這種寫法可以用來記錄 TimeoutException
已經失敗 10 次的錯誤。
void Main()
{
try
{
data = MakeWebRequest();
}
catch (TimeoutException e) when (failures++ < 10)
{
Console.WriteLine("Timeout error: trying again");
}
catch (Exception e) when (ConsoleLogException(e)) { }
}
最後一個寫法可以確保在 Debugger 在連接的狀態底下不會攔截錯誤,下面這段程式碼只要連接上 Debugger 那麼就可知道目前是
測試中那竟沒有必要攔截 TimeoutException
,只需要運作第一行的 ConsoleLogException
方法即可。
void Main()
{
try
{
data = MakeWebRequest();
}
catch (Exception e) when (ConsoleLogException(e)) { }
catch (TimeoutException e) when ((failures++ < 10) && (!System.Diagnostics.Debugger.IsAttached))
{
WriteLine("Timeout error: trying again");
}
}
Summary
這個做法透過 Exception Filters 會優先執行 when 字句裡的程式碼的這種特性來達到安插紀錄日誌的程式碼, 在龐大的項目中這個技巧可以幫助開發者更快的發現故障點。