核心警示:
你添加 try-catch 本想保護(hù)應(yīng)用,
結(jié)果卻:隱藏錯誤、觸發(fā)重試風(fēng)暴、讓故障追蹤難如登天。
在 .NET 中,try-catch 并非總是盟友——有時它正是系統(tǒng)無聲崩潰的元兇。
正確處理異常的關(guān)鍵:讓應(yīng)用高聲報錯、優(yōu)雅恢復(fù)、永不讓你猜謎!
?? 典型災(zāi)難代碼
try
{
var user = await _userService.GetUserAsync(id);
_logger.LogInformation("Fetched user");
}
catch (Exception ex) // 全類型捕獲
{
_logger.LogError(ex, "Something went wrong");
}
? 看似安全
? 靜默掩蓋根因
?? 違反關(guān)注點(diǎn)分離
?? 引發(fā)重試循環(huán)、丟失指標(biāo)、調(diào)試地獄
? 五大 try-catch 反模式(附解決方案)
? 修復(fù)方案 1:使用 when
過濾器
try
{
// 業(yè)務(wù)邏輯
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
_logger.LogWarning("用戶不存在"); // 精準(zhǔn)捕獲
}
優(yōu)勢:
?? 避免無關(guān)異常誤入
?? 保持處理邏輯精準(zhǔn)可控
?? 重要提示:僅捕獲可處理的異常。未知庫故障等極少數(shù)場景下,可用寬泛捕獲記錄日志后重新拋出(throw;
)
? 修復(fù)方案 2:預(yù)防代替捕獲
if (!File.Exists(path)) // 防御性檢查
{
_logger.LogWarning("文件缺失: {path}", path);
return;
}
// 而非盲目捕獲 FileNotFoundException
原則:
?? 防御性編程 > 異??刂屏?/span>
?? 根據(jù)場景合理選用,非萬能方案
? 修復(fù)方案 3:創(chuàng)建領(lǐng)域?qū)佼惓?/span>
public classPaymentDeclinedException : Exception// 自定義異常
{
public PaymentDeclinedException(string reason) : base(reason) { }
}
// 精準(zhǔn)捕獲可處理的異常
try
{
await _paymentService.ProcessAsync();
}
catch (PaymentDeclinedException ex) // 僅捕獲支付拒絕
{
_logger.LogWarning("支付拒絕: {reason}", ex.Message);
return BadRequest(ex.Message);
}
價值:
?? 提升代碼可讀性
?? 增強(qiáng)可測試性
?? 明確恢復(fù)路徑
? 修復(fù)方案 4:中間件統(tǒng)一處理
// 注冊異常處理中間件
app.UseExceptionHandler("/error");
// 集中處理錯誤響應(yīng)
app.Map("/error", (HttpContext context) =>
{
var feature = context.Features.Get<IExceptionHandlerFeature>();
return Results.Problem(detail: feature?.Error.Message);
});
優(yōu)勢:
?? 全局統(tǒng)一錯誤響應(yīng)
?? 業(yè)務(wù)代碼零污染
? 修復(fù)方案 5:后臺任務(wù)禁止吞沒異常
try
{
await _processor.RunAsync();
}
catch (Exception ex)
{
_logger.LogCritical(ex, "任務(wù)失敗");
throw; // 重新拋出!讓編排器(如Azure Functions)可見故障
}
關(guān)鍵原則:
?? 后臺任務(wù)靜默失敗 = 定時炸彈
?? 必須拋出以便觸發(fā)重試/告警
? 修復(fù)方案 6:分層彈性策略(Polly)
services.AddHttpClient("Users")
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, retry => TimeSpan.FromSeconds(Math.Pow(2, retry)))); // 指數(shù)退避重試
核心價值:
?? HTTP層處理瞬時故障
?? 業(yè)務(wù)代碼無侵入
?? 專家級技巧:生產(chǎn)就緒清單
?? 終極忠告
try-catch 不是安全網(wǎng),而是精密手術(shù)刀
我親歷的 .NET 生產(chǎn)事故中,從未因未捕獲異常引發(fā)宕機(jī),
真正的災(zāi)難總是:
?? 異常被捕獲 → 記錄日志 → 靜默忽略 → 用戶發(fā)現(xiàn)故障時已無力回天
沒有告警,沒有重試,只有沉默的崩潰。
讓錯誤暴露在陽光下,才是真正的韌性。
該文章在 2025/7/24 14:53:37 編輯過