Phân biệt bug, error và exception Bug là lỗi về mặt lập trình do lập trình viên không kiểm soát được mã nguồn, bug ném ra một ngoại lệ nhưng để sửa các bug ta phải viết lại đoạn mã E
Trang 1Cấu trúc quản lí lỗi
Exception Handling
Trang 2Phân biệt bug, error và
exception
Bug là lỗi về mặt lập trình do lập trình viên không kiểm soát được mã nguồn, bug ném ra một ngoại lệ nhưng để sửa các bug ta phải viết lại đoạn mã
Error là lỗi do người dùng tạo ra Ví dụ khi nhập số thì người dùng lại nhập các kí tự… Các error cũng ném ra exception nhưng có thể tiên đoán trước và yêu cầu người dùng nhập lại đến khi phù hợp
Ngoài các bug, error, vẫn còn nhiều tình huống xảy ra lỗi mà ta không thể lường trước: lỗi tràn bộ nhớ, lỗi truy cập tập tin không tồn tại… Ngoại lệ là các lỗi xảy ra trong quá trình chạy chương trình
Trang 3Khi ngoại lệ không được
bắt
Khi có 1 ngoại lệ được ném ra, hàm đang thực thi sẽ bị tạm dừng, vùng nhớ stack sẽ duyệt ngược lại để tìm trình
xử lí ngoại lệ
Nếu hàm hiện tại không có trình xử lí thì sẽ xét tiếp đến hàm gọi nó, nếu không có hàm gọi nào có trình xử lí thì sẽ ném cho NET runtime xử lí, đồng nghĩa với việc chương trình sẽ bị dừng lại đột ngột
Trình quản lí lỗi là 1 đoạn mã được thiết kế để xử lí các ngoại lệ được ném ra
Trang 4Các thành phần của khối
lệnh xử lí ngoại lệ trong C#
1 lớp chứa thông tin về ngoại lệ
1 thành viên ném 1 thể hiện của lớp chứa ngoại lệ
1 khối lệnh có thể xảy ra ngoại lệ
1 khối lệnh xử lí ngoại lệ khi nó xảy ra
Trang 5Lớp chứa thông tin về
ngoại lệ
Là 1 lớp kế thừa từ các class Exception có sẵn trong C#
System.Exception: class ngoại lệ tổng quát, mọi class về ngoại lệ đều kế thừa trực tiếp hoặc gián tiếp từ class này
System.SystemException: dùng cho các ngoại lệ được sinh ra trong thời gian chạy của NET, ví dụ:
StackOverflowException xảy ra khi bộ nhớ của Stack đầy…
System.ApplicationException: dùng cho các ngoại lệ được định nghĩa bởi các hãng thứ ba
Trang 6Một vài lớp exception hay
dùng
MethodAccessException: lỗi truy cập đến các thành viên không được phép truy cập
DivideByZeroException: lỗi chia zero
FormatEception: lỗi không đúng định dạng
IndexOutOfRangeException: lỗi vượt quá chỉ số của array/list…
NullReferenceException: lỗi tham chiếu null không hợp lệ
ArgumentNullException: lỗi đối số truyền vào là null
InvalidCastException: lỗi phép gán không hợp lệ
ArgumentException: lỗi tham số khi gọi hàm
Trang 7Các thuộc tính của lớp
Exception tổng quát
HelpLink (string): URL dẫn đến 1 tập tin hoặc 1 website chứa thông tin đầy đủ về ngoại lệ
Data (IDictionary): trả về tập hợp các cặp key/value do lập trinh viên định nghĩa, mặc định thuộc tính này là rỗng
HResult (int): trả về mã hexa của ngoại lệ
InnerException (Exception): nếu ngoại lệ này được ném từ bên trong một khối catch , nó chứa đựng đối tượng ngoại lệ mà gửi đoạn mã vào trong khối catch
Message (string): chuỗi mô tả ngoại lệ
Source (string): tên ứng dụng hoặc đối tượng gây ra lỗi
StackTrace (string): chuỗi diễn tả phương thức gọi stack
TargetSite (MethodBase): trả về đối tượng mô tả phương thức gây ra ngoại lệ
Trang 8Ném ngoại lệ với từ khóa
throw
public class Humans
{ public int Age {
get { return Age; } set
{
if (value >= 0) {
Age = value; Console.WriteLine(“Tuoi la {0}”, Age);
} else throw new Exception(“Tuoi khong chinh xac”); }
} }
Khi một đối tượng xảy ra lỗi, đối tượng này có thể
ném lỗi cho đoạn code gọi nó với từ khóa throw, cái
được ném ra là 1 đối tượng chứa thông tin về ngoại lệ
Trang 9Bắt ngoại lệ với khối lệnh
try-catch
static void Main(string[] args) {
Console.WriteLine(“Simple Exception Example”);
Humans a = new Humans() { Age = 30; } try
{ for (int i = 0; i < 4; i++) a.Age -= 10;
} catch (Exception e) {
Console.WriteLine(“Exception Message: {0}”, e.Message); }
}
Để bắt ngoại lệ, ta sử dụng khối lệnh try-catch Khối
try dùng để chứa đoạn lệnh có khả năng ném ra ngoại
lệ Khối catch sẽ bắt ngoại lệ để xử lí
Trang 10Bắt ngoại lệ với khối lệnh
try-catch
Ở ví dụ trên, ta giảm tuổi của a xuống 4 lần, từ 30 xuống 20, 10, 0 và -10 thì xảy ra lỗi, hàm set của phương thức Age
sẽ ném ra 1 ngoại lệ Sau đó khối catch sẽ bắt ngoại lệ này và in ra màn hình thông báo lỗi
Kết quả:
Tuoi la 30 Tuoi la 20 Tuoi la 10 Tuoi la 0 Exception Message: Tuoi khong chinh xac
Để bắt ngoại lệ, ta sử dụng khối lệnh try-catch Khối
try dùng để chứa đoạn lệnh có khả năng ném ra ngoại
lệ Khối catch sẽ bắt ngoại lệ để xử lí
Trang 11Bắt ngoại lệ với nhiều khối
catch
while (true) {
try
{ Console.Write(“Nhap 1 so tu 1 den 10, nhap rong de thoat: ”);
string input = Console.ReadLine();
if (input == “”) break; int index = Convert.ToInt32(input);
if (index < 1 || index > 10) throw new IndexOutOfRangeException(“Ban da nhap so ” + input);
Console.WriteLine(“So ban nhap la {0}”, index);
}
catch(IndexOutOfRangeException e) {
Console.WriteLine(“Co loi! Ban phai nhap so tu 1 den 10! {0}”, e.Message); }
catch(Exception e) {
Console.WriteLine(“Co loi! {0}”, e.Message);
} }
Trang 12Bắt ngoại lệ với nhiều khối
catch
Khi chạy:
Nhap 1 so tu 1 den 10, nhap rong de thoat: 5
So ban nhap la 5 Nhap 1 so tu 1 den 10, nhap rong de thoat: 20
Co loi! Ban phai nhap so tu 1 den 10! Ban da nhap so 20 Nhap 1 so tu 1 den 10, nhap rong de thoat: abc
Co loi! Input string was not in a correct format
Nhap 1 so tu 1 den 10, nhap rong de thoat:
Trang 13Khối catch không có tham
số
Khối catch không có tham số sẽ bắt được mọi ngoại lệ xảy ra của những ngoại lệ không được viết trong C# hoặc không được quản lí trong C# Ví dụ trong C++, mọi biến đều có thể được ném ra như 1 ngoại lệ, nếu ta gọi đoạn mã này trong C++, nó sẽ bắt được các ngoại lệ không dẫn xuất từ class System.Exception
catch
{ Console.WriteLine(“Co loi nao do xay ra”);
}
Trang 14Khối lệnh finally
Nhiều khi chúng ta cần phải thực hiện 1 vài lệnh dù cho có hoặc không xảy ra ngoại lệ Ví dụ: khi ta mở 1 file và thao tác trên file đó, dù có hoặc không xảy ra ngoại lệ thì ta vẫn phải đóng file lại
Một cách giải quyết là đưa cậu lệnh đóng file vào trong cả khối try và khối catch Tuy nhiên cách này gây ra sự trùng lặp lệnh
C# cung cấp khối lệnh finally để thực hiện thao tác này
Trang 15Ví dụ về khối lệnh
try-catch-finally
string path = @"c:\users\public\test.txt";
var file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{ file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e) {
Console.WriteLine("Error reading from {0} Message = {1}", path, e.Message); }
finally
{
if (file != null) {
file.Close();
} }