- Khác ở thời điểm stack được unwind.
- Biểu thức trong
when(exception filter) chạy ở first pass của cơ chế xử lý exception — tức là trước khi stack bị gỡ. - Còn
catchlà second pass: vào được thâncatchnghĩa là stack đã unwind xong rồi,throw;chỉ ném lại chứ không khôi phục được trạng thái đã mất.
csharp
try { await CallPartnerAsync(); }
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.TooManyRequests)
{
await Task.Delay(backoff);
}Hệ quả thực tế:
- Debug và crash dump: nếu filter trả
false, debugger dừng ngay tại chỗ ném với đầy đủ frame và biến cục bộ. Với kiểu catch-rồi-rethrow, ngữ cảnh đó đã biến mất khi dump được tạo. throw;vẫn nối thêm vào stack trace ở điểm rethrow, khiến trace khó đọc hơn so với việc không bao giờ bắt.- Ghi log không nuốt exception: một mẹo phổ biến là
when (Log(ex))vớiLogluôn trảfalse— log được ghi ngay lúc lỗi phát sinh mà exception vẫn tiếp tục lan lên.
Hai điều cần cẩn thận: biểu thức filter không nên ném exception (nếu ném, nó bị nuốt và filter coi như false) và không nên có side effect nặng, vì nó chạy trong ngữ cảnh xử lý exception.