Chapter 5 - Item 50 : Leverage Side Effects in Exception filters

Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得

延續 Item 49 的議題,我們還可以利用例外過濾做更多應用。比如用來做 Logging;以往在做例外日誌寫入時,如果有多種例外,常常需要在不同的 catch 區塊各自呼叫 logging 方法:造成重複的程式碼變多了。利用例外過濾的特性可以輕鬆解決這個問題。

範例程式碼:

var failures = 0;	
try
{
	MakeWebRequest();
}
catch (Exception ex) when (ConsoleLogException(ex))
{ }
catch (TimeoutException ex ) when(failures++ < 10)
{
	Console.WriteLine("Timeout error : try again.");
}

public void MakeWebRequest()
{
	throw new TimeoutException();
}

public static bool ConsoleLogException(Exception e)
{
	var oldColor = Console.ForegroundColor;
	Console.ForegroundColor = ConsoleColor.Red;
	Console.WriteLine($"Error : {e}");
	Console.ForegroundColor = oldColor;
	return false;
}

由於 when 後面的條件式會先執行,依照執行結果才進入 catch 區塊;我們利用這樣的特性,獲取基礎例外類別並在 ConsoleLogException 寫入日誌且回傳 false。該 catch 區塊永遠不會進入,繼續往下一個尋找。這樣就解決了重複的程式碼。

當然也可以任意的排列組合與套用不同的條件式。

try
{
	MakeWebRequest();
}
catch (TimeoutException ex) when (failures++ < 10)
{
	Console.WriteLine("Timeout error : try again.");
}
catch (Exception ex) when (ConsoleLogException(ex)) // 當先前的例外處理皆不符合時寫入日誌。
{ }

try
{
	MakeWebRequest();
}
catch (Exception ex) when (ConsoleLogException(ex))
{ }
catch (TimeoutException ex) when (failures++ < 10 &&
System.Diagnostics.Debugger.IsAttached == false) // 當程式有 attch 至 IDE Debugger時擲出例外,立刻指出出問題的地方。
{
	Console.WriteLine("Timeout error : try again.");
}
結論:
1. 利用例外條件式來減少重複的程式碼。
2. 利用例外條件式來處理不同的額外判斷。