Exception
Nội dung bài · 6 mục
Người dùng gõ "abc" vào ô số lượng, file cấu hình bị xoá, mạng rớt giữa chừng. Những lỗi này chỉ xuất hiện lúc chạy. Không xử lý thì chương trình dừng ngay. Bài này hướng dẫn cách bắt lỗi và cách tự báo lỗi.
Khái niệm
💥 Exception: object mô tả một lỗi xảy ra lúc chạy, làm chương trình dừng nếu không ai bắt.
🧯 try/catch: cặp khối dùng để chạy thử code trong try và xử lý exception trong catch nếu có lỗi.
🚨 throw: câu lệnh ném ra một exception, thường viết kèm new để tạo exception đó.
Ví dụ
string input = "abc";
try
{
int quantity = int.Parse(input);
Console.WriteLine($"Số lượng: {quantity}");
}
catch (FormatException)
{
Console.WriteLine("Vui lòng nhập một con số");
}int.Parse("abc")némFormatException. Code còn lại trongtrybị bỏ qua, chương trình nhảy sangcatch.catch (FormatException)chỉ bắt đúng loại lỗi đó. Loại khác vẫn làm chương trình dừng.- Có thể thêm khối
finallysaucatch. Code trongfinallyluôn chạy, dù có lỗi hay không.
Tên exception hay gặp: FormatException (sai định dạng),
NullReferenceException (dùng biến đang là null), ArgumentException (tham số không
hợp lệ), InvalidOperationException (thao tác không hợp lệ lúc đó).
Tự ném exception
Khi method nhận dữ liệu vô lý, hãy throw để báo ngay thay vì âm thầm chạy
sai:
decimal Total(decimal price, int quantity)
{
if (quantity <= 0)
{
throw new ArgumentException(
"Số lượng phải lớn hơn 0");
}
return price * quantity;
}
Console.WriteLine(Total(5000m, 2)); // 10000Thử ngay
Chép method Total ở trên vào Program.cs, thay dòng gọi Total bằng:
try
{
Console.WriteLine("A");
Console.WriteLine(Total(5000m, 0));
Console.WriteLine("B");
}
catch (ArgumentException ex)
{
Console.WriteLine($"Lỗi: {ex.Message}");
}
finally
{
Console.WriteLine("C");
}Đoán trước khi chạy: chữ "B" có được in không?
Xem kết quả
A
Lỗi: Số lượng phải lớn hơn 0
C"B" không được in. Exception xảy ra ở dòng giữa, nên phần còn lại của try bị
bỏ qua.
ex.Message là nội dung đã truyền lúc throw. finally vẫn chạy.
Lỗi hay gặp
catch rỗng. Lỗi bị nuốt mất, chương trình chạy sai mà không ai biết.
// SAI — lỗi xảy ra nhưng không ai hay
try
{
int quantity = int.Parse("abc");
}
catch (Exception)
{
}// ĐÚNG — ít nhất phải báo cho người dùng
try
{
int quantity = int.Parse("abc");
}
catch (FormatException)
{
Console.WriteLine("Số lượng không hợp lệ");
}Bắt Exception trước loại cụ thể. Exception bắt được mọi lỗi, nên
catch đứng sau nó không bao giờ chạy tới.
// SAI — lỗi compile: catch thứ hai không bao giờ chạy
try
{
int.Parse("abc");
}
catch (Exception)
{
Console.WriteLine("Có lỗi");
}
catch (FormatException)
{
Console.WriteLine("Sai định dạng");
}// ĐÚNG — loại cụ thể đứng trước
try
{
int.Parse("abc");
}
catch (FormatException)
{
Console.WriteLine("Sai định dạng");
}
catch (Exception)
{
Console.WriteLine("Có lỗi");
}Tóm tắt
- Exception là lỗi lúc chạy, không bắt thì chương trình dừng.
trychạy thử,catchxử lý lỗi,finallyluôn chạy.- Bắt đúng loại exception cụ thể và đặt nó trước
Exception. - Dùng
throwkhi dữ liệu vô lý, đừng âm thầm chạy tiếp. - Không để
catchrỗng.
Tự kiểm tra
0/3 câuTrong try, int.Parse("abc") ném FormatException. Sau try chỉ có catch (ArgumentException). Chuyện gì xảy ra?
Method SetPrice(decimal price) nhận giá âm. Cách xử lý nào hợp lý nhất?
Khối nào luôn chạy, dù try có lỗi hay không?