Xử lý ngoại lệ trong C# là một cơ chế tích hợp sẵn trong NET framework để phát hiện và xử lý các lỗi xảy ra trong quá trình chạy chương trình. Trong C#, chúng ta sử dụng 3 từ khóa quan trọng là try, catch, và finally. Hãy cùng khám phá chi tiết trong bài viết dưới đây của Mytour.
Xử lý ngoại lệ (Exception Handling) trong C#
1. Giới thiệu về Xử lý Ngoại lệ (Exception Handling) trong C#.
2. Ngoại lệ không được bắt (Uncaught Exception).
3. Khối catch trong C#.
4. Bắt toàn bộ ngoại lệ trong C#.
5. Ném một ngoại lệ.
6. Ném lại một ngoại lệ.
7. Các loại ngoại lệ chuẩn trong C#.
8. Ngoại lệ do người dùng định nghĩa.
1. Giới thiệu về Xử lý Ngoại lệ (Exception Handling) trong C#
Như đã đề cập trước đó, xử lý ngoại lệ là một phần của .NET framework, giúp phát hiện và xử lý các lỗi xảy ra trong quá trình chạy chương trình. .NET framework cung cấp nhiều ngoại lệ chuẩn để xử lý các tình huống khác nhau.
Các tình huống bất thường này có thể là do lỗi từ người dùng, lỗi logic hoặc lỗi hệ thống. Trong trường hợp không có cơ chế xử lý từ người dùng, môi trường runtime .NET sẽ áp dụng cơ chế mặc định và chấm dứt chương trình.
C# sử dụng 3 từ khóa quan trọng: try, catch, và finally để xử lý ngoại lệ. Từ khóa try chứa các lệnh có thể gây ra ngoại lệ, catch xử lý nếu có ngoại lệ, và finally đảm bảo thực hiện quá trình dọn dẹp.
Dưới đây là cấu trúc chung của các từ khóa try - catch - finally trong C#:
Nếu có bất kỳ ngoại lệ nào xảy ra trong khối try, control sẽ chuyển sang khối catch và sau đó đến khối finally.
Tuy nhiên trong C#, khối catch và khối finally đều là tùy chọn. Khối try có thể tồn tại cùng một hoặc nhiều khối catch hoặc khối finally, hoặc cả cả 2 khối catch và finally.
Nếu không có ngoại lệ xảy ra trong khối try, control sẽ tự động chuyển đến khối finally. Các lệnh bên trong khối finally luôn được thực thi. Lưu ý rằng lỗi có thể xảy ra nếu control rời khỏi khối finally bằng cách sử dụng break, continue, return hoặc goto.
Trong C#, ngoại lệ là các đối tượng thuộc kiểu Exception. Exception là cơ sở cho mọi ngoại lệ trong C#.
C# cung cấp nhiều ngoại lệ chuẩn, nhưng nếu bạn muốn, bạn có thể tạo các lớp ngoại lệ riêng, miễn là chúng kế thừa từ lớp Exception hoặc một trong số các lớp dẫn xuất chuẩn, như DivideByZeroExcpetion hay ArgumentException, ... .
2. Uncaught Exception
Chương trình dưới đây khi biên dịch sẽ xuất hiện lỗi trong quá trình thực thi. Việc chia cho 0 được coi là không bình thường và chương trình sẽ kết thúc với thông báo lỗi.
Uncaught exception trong bất kỳ context nào sẽ propagate lên đến higher context để tìm khối catch phù hợp để xử lý. Nếu không tìm thấy khối catch phù hợp, cơ chế mặc định của .NET runtime sẽ chấm dứt toàn bộ chương trình.
Chương trình sau khi được sửa đổi với cơ chế xử lý ngoại lệ sẽ có dạng như sau. Ở đây, chúng ta sử dụng đối tượng từ lớp ngoại lệ chuẩn DivideByZeroException để xử lý trường hợp chia cho số 0.
Kết quả trả về từ đoạn mã trên sẽ có dạng như sau:
Trong ví dụ này, chương trình không kết thúc ngay lập tức; thay vào đó, quyền kiểm soát chuyển từ điểm xảy ra ngoại lệ bên trong khối try sang khối catch. Nếu có bất kỳ khối catch nào phù hợp, quá trình thực thi các lệnh bên trong khối catch sẽ tiếp tục. Nếu khối finally xuất hiện, mã bên trong khối này sẽ được thực thi.
Một điều quan trọng là khối catch trong C# là tùy chọn. Dưới đây là một ví dụ về chương trình hợp lệ trong C#:
Tuy nhiên, trong trường hợp này, không có xử lý ngoại lệ trong khối catch, dẫn đến việc kết thúc quá trình thực thi. Trước khi kết thúc, các lệnh trong khối finally sẽ được thực thi. Trong C#, khối try phải đến sau khối catch hoặc khối finally.
3. Khối catch trong C#
Một đoạn mã try có thể tạo ra nhiều ngoại lệ, và chúng ta có thể xử lý chúng thông qua nhiều khối catch. Lưu ý rằng khối catch chuyên dụng sẽ được ưu tiên trước khối catch tổng quát; nếu không, trình biên dịch sẽ báo lỗi.
4. Xử lý tất cả ngoại lệ trong C#
Bằng cách cung cấp một khối catch mà không có dấu ngoặc vuông hoặc tham số, chúng ta có thể bắt tất cả các ngoại lệ xảy ra trong khối try.
Hoặc, chúng ta cũng có thể sử dụng khối catch với tham số kiểu Exception để bắt tất cả các ngoại lệ xảy ra trong khối try, vì tất cả các ngoại lệ trong C# đều kế thừa trực tiếp hoặc gián tiếp từ lớp Exception.
Dưới đây là một đoạn mã minh họa việc xử lý tất cả các loại ngoại lệ bằng đối tượng Exception.
5. Ném một Exception
Trong ngôn ngữ lập trình C#, chúng ta có thể kích hoạt một ngoại lệ bằng từ khóa 'throw'. Cấu trúc ném một ngoại lệ trong C# có dạng như sau:
throw exception_obj;
Ví dụ, đoạn mã dưới đây tạo ra một ngoại lệ loại ArgumentException:
6. Ném lại một ngoại lệ
Sau khi bắt được ngoại lệ trong khối catch, chúng ta có thể chọn ném lại nó vào ngữ cảnh cao hơn bằng cách sử dụng từ khóa throw.
Chương trình minh họa cách ném lại một ngoại lệ trong ngôn ngữ lập trình C#:
7. Ngoại lệ Chuẩn trong C#
Trong lập trình C#, chúng ta gặp 2 loại ngoại lệ: ngoại lệ do chương trình và ngoại lệ do hệ thống chung của ngôn ngữ.
Lớp System.Exception là nền tảng của mọi loại ngoại lệ trong C#. Có nhiều lớp ngoại lệ kế thừa từ System.Exception như ApplicationException và SystemException, chúng đóng vai trò cơ sở cho đa số ngoại lệ thời gian chạy khác. Các lớp ngoại lệ khác thừa kế từ System.Exception bao gồm IOException, WebException, ... .
Trong quá trình chạy, hệ thống ném ngoại lệ SystemException. ApplicationException thường được ném bởi chương trình người dùng hơn là hệ thống. SystemException bao gồm ExecutionEngineException, StackOverflowException, ... .
8. Tự Định Nghĩa Ngoại Lệ
Trong C#, chúng ta có khả năng tạo ra các lớp ngoại lệ riêng, tuy nhiên, Exception phải là lớp cơ sở cuối cùng cho tất cả các lớp ngoại lệ trong C#. Do đó, các lớp ngoại lệ do người dùng định nghĩa cần phải kế thừa từ lớp Exception hoặc một trong những lớp dẫn xuất tiêu chuẩn của Exception.
Bài viết trên đây của Mytour đã giới thiệu về xử lý ngoại lệ (Exception Handling) trong C#. Nếu một ngoại lệ được định nghĩa trước đó trong không gian tên System mô tả điều kiện ngoại lệ, ngoại lệ đó sẽ liên quan đến lớp. Cuối cùng, nếu mã bắt gặp một ngoại lệ mà không xử lý, bạn có thể cân nhắc bọc ngoại lệ đó với thông tin bổ sung trước khi ném lại nó. Để biết thêm về C#, hãy tìm hiểu về File I/O trong C#.