Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得
例外處理是一種增加程式可靠度的做法,但通常我們在抓取例外時,常常只用到 Exception 父類別。這樣的通用資訊對程式除錯沒有太大幫助(範圍太大且不知道是哪一種例外);作者建議針對可能出現的例外,自定義對應的例外類別;能讓錯誤訊息與程式更完整。
擁有自定義例外處理的程式使用方式:
try
{
Foo();
Bar();
}
catch (MyFirstApplicationException e1)
{
FixProblem(e1);
}
catch (AnotherApplicationException e2)
{
ReportErrorAndContinue(e2);
}
catch (YetAnotherApplicationException e3)
{
ReportErrorAndShutdown(e3);
}
catch (Exception e)
{
ReportGenericError(e);
throw;
}
finally
{
CleanupResource();
}
不同的例外有不同的處置方式,程式開發者可以利用 API 提供的例外類別做出相應處置。如果沒有定義不同的例外類別,開發者就只能利用 Exception 父類別中的訊息去推敲,造成流程控制困難。
不好的寫法:
void SampleTwo()
{
try
{
Foo();
Bar();
}
catch (Exception e)
{
switch (e.TargetSite.Name)
{
case "Foo":
FixProblem(e);
break;
case "Bar":
ReportErrorAndContinue(e);
break;
default:
ReportErrorAndShutdown(e);
throw;
}
}
finally
{
CleanupResource();
}
}
看起來很乾淨,統一抓取 Exception 父類別後判斷。但這是不好的做法,僅僅依靠 hard code 方法名稱判斷;若日後方法名修改,則此判斷就失效。
作者建議在自創例外類別時,保留建構子實作。
[Serializable]
public class MyFirstApplicationException : Exception
{
public MyFirstApplicationException()
: base()
{
}
public MyFirstApplicationException(string s)
: base(s)
{
}
public MyFirstApplicationException(string s, Exception e)
: base(s, e)
{
}
// .NET Core 有可能不支援。
protected MyFirstApplicationException(SerializationInfo info, StreamingContext cxt)
: base(info, cxt)
{
}
}
最後,如果程式有利用到第三方元件;且有可能擲出例外時,也是用自定義例外將底層例外包裝,讓擲出的例外可讀性更好。
public double DoSomeWork()
{
// 第三方元件可能拋出例外。
return ThirdPartyLibrary.ImportantRoutine();
}
public double DoSomeWork2()
{
try
{
// 第三方元件可能拋出例外。
return ThirdPartyLibrary.ImportantRoutine();
}
catch (ThirdPartyException e)
{
var msg = $"Problem with {ToString()} using library";
throw new DoingSomeWorkException(msg, e);
}
}
結論:
1. 利用自定義例外類別,讓呼叫端有機會做相應處理。
2. 利用自定義例外類別封裝底層拋出的例外,提高呼叫端收到的例外訊息可讀性。
1. 利用自定義例外類別,讓呼叫端有機會做相應處理。
2. 利用自定義例外類別封裝底層拋出的例外,提高呼叫端收到的例外訊息可讀性。