|
|
|
|
|
你的代碼中是否存在需要多次處理特定異常的情況?我們經(jīng)常會(huì)遇到這樣的情況,我們必須根據(jù)某種條件執(zhí)行不同的異常處理邏輯。
假設(shè)我們想在捕捉異常HttpRequestException
時(shí),StatusCode=400(Bad Request)時(shí)以一種方式處理,而StatusCode=404 (Not Found)時(shí)以另一種方式處理,你可能想到編寫一個(gè) if
語(yǔ)句來(lái)檢查條件:
try
{
await GetBlogsFromApi();
}
catch (HttpRequestException e)
{
if (e.StatusCode == HttpStatusCode.BadRequest)
{
HandleBadRequest(e);
}
else if (e.StatusCode == HttpStatusCode.NotFound)
{
HandleNotFound(e);
}
}
雖然這可行,但它不是最干凈的方法,有一個(gè)你可能不知道的更好的解決方案。
實(shí)際上,try-catch
可以使用多個(gè)catch
字句,發(fā)生異常時(shí),按指定順序從上到下檢查 catch
子句。但是,對(duì)于任何拋出的異常,最多只catch
執(zhí)行一個(gè)塊。如前例所示,你可以省略異常變量的聲明并在 catch
子句中僅指定異常類型。沒(méi)有任何指定異常類型的 catch
子句匹配任何異常,如果存在,則必須是最后一個(gè) catch
子句。
以下是我們?nèi)绾胃鶕?jù)特定條件優(yōu)雅地捕獲相同的異常:
try
{
await GetBlogsFromApi();
}
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.BadRequest)
{
HandleBadRequest(e);
}
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)
{
HandleNotFound(e);
}
這個(gè)就是異常when過(guò)濾器,使用異常過(guò)濾器來(lái)提供單個(gè)catch
塊來(lái)處理兩種指定類型的異常。
如果它們通過(guò)異常過(guò)濾器區(qū)分catch
,你可以為相同的異常類型提供多個(gè)子句,其中一個(gè)子句可能沒(méi)有異常過(guò)濾器。如果存在這樣的子句,它必須是指定該異常類型的子句的最后一個(gè)。除了異常類型,你可以指定一個(gè)異常過(guò)濾器,進(jìn)一步檢查異常并決定相應(yīng)的catch
塊是否處理該異常。
異常過(guò)濾器是關(guān)鍵字后面的布爾表達(dá)式when
,當(dāng)我們需要添加更多條件時(shí),這種方法更簡(jiǎn)潔、更容易擴(kuò)展。
如果要重新拋出捕獲的異常,請(qǐng)使用throw
語(yǔ)句,如以下示例所示:
try
{
var result = Process(-3, 4);
Console.WriteLine($"Processing succeeded: {result}");
}
catch (Exception e)
{
LogError(e, "Processing failed.");
throw;
}
注意throw;
保留異常的原始堆棧跟蹤,它存儲(chǔ)在Exception.StackTrace
屬性中,與此相反,throw e;
更新 的StackTrace屬性e
。 參考文章:
[C#技巧]C#重新拋出異常的正確方法,注意不是throw e!
相關(guān)文章