C# Cơ bản .NET Core §1) Cài đặt, chương trình C# đầu tiên §2) Biến, kiểu dữ liệu và nhập/xuất §3) Toán tử số học và gán §4) So sánh, logic và lệnh if, switch §5) Vòng lặp for, while §6) Phương thức - Method §7) Phương thức - Delegate §8) Lớp - Class §9) Kiểu vô danh và dynamic §10) Biểu thức lambda §11) Event §12) Hàm hủy - Quá tải toán tử - thành viên tĩnh - indexer §13) Lớp lồng nhau - namespace §14) null và nullable §15) Mảng §16) Chuỗi ký tự §17) Tính kế thừa §18) Tính đa hình - abstract - interface §19) Struct và Enum §20) Ngoại lệ Exeption §21) IDisposable - using §22) File cơ bản §23) FileStream §24) Generic §25) Collection - List §26) SortedList §27) Queue / Stack §28) Linkedlist §29) Dictionary - HashSet §30) Phương thức mở rộng §31) ObservableCollection §32) LINQ §33) (Multithreading) async - bất đồng bộ §34) Type §35) Attribute Annotation §36) DI Dependency Injection §37) (Multithreading) Parallel §38) (Networking) HttpClient §39) (Networking) HttpMessageHandler §40) (Networking) HttpListener §41) (Networking) Tcp TcpListenerr/TcpClient §42) (ADO.NET) SqlConnection §43) (ADO.NET) SqlCommand §44) (EF Core) Tổng quan §45) (EF Core) Tạo Model §46) (EF Core) Fluent API §47) (EF Core) Query §48) (EF Core) Scaffold §49) (EF Core) Migration §50) (ASP.NET CORE) Hello World! §51) (ASP.NET CORE) Middleware §52) (ASP.NET CORE) Map - Request - Response §53) (ASP.NET CORE) IServiceCollection - MapWhen §54) (ASP.NET CORE) Session - ISession §55) (ASP.NET CORE) Configuration §56) (ASP.NET CORE MVC) Controller - View

Ngoại lệ Exception

Ngoại lệ (exception) là vấn đề - lỗi phát sinh trong quá trình thực thi chương trình. Thường khi chương trình đang chạy mà phát sinh ngoại lệ (lỗi) thì dẫn đến chương trình kết thúc ngay lập tức. Có vô số nguyên nhân để chương trình đang chạy mà phát sinh ngoại lệ, ví dụ:

  • Dữ liệu người dùng nhập sai, mà chương trình không kiểm soát được
  • Thực hiện các phép toán không được phép (như chia một số cho 0)
  • Thao tác với tài nguyên không tồn tại (như mở file không có trên đĩa, kết nối đến CSDL không tồn tại ...)
  • Thiếu bộ nhớ
  • ...

Trong C# khi có một lỗi phát sinh hầu hết các lỗi đều có thể quản lý bởi thư viện C# thì nó sẽ phát sinh ra một đối tượng lớp Exeption (System.System) hoặc đối tượng lớp nào đó kế thừa từ Exception

Khi một đối tượng lớp Exception sinh ra - mà chương trình không chủ động xử lý đối tượng này thì chương trình sẽ kết thúc. Đối tượng lớp Exception chứa trong nó các thông tin về lỗi (dòng thông báo, nguyên nhân lỗi, nơi phát sinh lỗi ...)

Thử phát sinh một Exception

Chạy đoạn code sau:

static void Main(string[] args)
{

    int[] mynumbers = new int[] {1,2,3};
    int i = mynumbers[10];     // chỗ này phát sinh lỗi
}

Đoạn code trên khi chạy sẽ phát sinh lỗi bởi vì, mynumbers là mảng có 3 phần tử, nhưng chi đọc lại cố tình truy cập đến phần tử thứ 11 mynumber[10]

CS

Do lỗi này không được xử lý, nên chương trình kết thúc ngay lập tức và có đọc được thông báo về lỗi như hình trên.

Xử lý ngoại lệ - Exception

Nếu ngoại lệ phát sinh mà không xử lý thì chương trình sẽ dừng đột ngột - nếu muốn xử lý ngoại lệ thì ta cần bắt lấy nó và điều hướng chương trình một cách thích hợp. Để bắt ngoại lệ ta sử dụng câu lệnh try ... catch ... như sau:

try {
   // code được giám sát để bắt lỗi nếu có
}
catch (Exception loi)
{
  // Khỗi thực thi - khi có lỗi - đối tượng Exception bắt được lưu ở biến loi
}

Như vậy đoạn code nào muốn giám sát để bắt ngoại lệ - thì đưa vào khối try, nếu ngoại lệ xảy ra do code trong khối đó thì sẽ bắt được - chương trình sẽ không kết thúc mà lập tức chuyển sang khối catch, tại đó bạn có ngay đối tượng lớp Exception - bạn cần xử lý theo logic ứng dụng của bạn điều hướng chương trình một cách thích hợp ở đây.

Đối tượng lớp Exception có một số thuộc tính, tiện dụng cho bạn gỡ rối đó là:

  • Message chuỗi chứa nội dung thông báo lỗi
  • StackTrace chuỗi chứa các bước thực thi chương trình cho đến khi bị lỗi (có chứa các phương thức, hàm khi thực thi gây lỗi, vị trí file lỗi ...)
  • Source chứa tên ứng dụng hoặc đối tượng bị lỗi

Thực hành bắt lỗi:

static void Main(string[] args)
{
    try {
        // khối này được giám sát để bắt lỗi - khi nó phát sinh
        int[] mynumbers = new int[] {1,2,3};
        int i = mynumbers[10];                  // dòng này phát sinh lỗi
        Console.WriteLine(i);                   // dòng này không được thực thi vì lỗi trên
    }
    catch (Exception loi)
    {
        // khối này thực thi khi bắt được lỗi
        Console.WriteLine("Có lỗi rồi");
        Console.WriteLine(loi.Message);
    }

}
Có lỗi rồi
Index was outside the bounds of the array.

Bắt nhiều ngoại lệ

Trong .NET từ lớp cơ sở Exception nó xây dựng nên rất nhiều loại ngoại lệ khác phục vụ chi tiết cho từng loại lỗi phát sinh khác nhau như: FileNotFoundException, FormatException, OutOfMemoryException, ArgumentException, NullReferenceException, IndexOutOfRangeException, DivideByZeroException...

Để bắt cụ thể một loại ngoại lệ nào đó chỉ việc thêm một khối catch tương ứng với ngoại lệ đó.

try {
    int x = 10;
    int y = 0;
    int z = x / y;

}
catch (DivideByZeroException e1) {
    Console.WriteLine(e1.Message);
}
catch (Exception e2) {
    Console.WriteLine(e2.Message);
}

Khi có ngoại lệ chia một số cho 0, thì khối catch với ngoại lệ kiểu DivideByZeroException được thi hành, còn ngoại lệ khác sẽ do khối catch thứ 2 thi hành. Bằng cách như vậy bạn có thể khai báo nhiều khối catch tùy nhu cầu.

Thêm vào khối finally

Trong lệnh try ... catch, bạn có thể thêm một tùy chọn là khối finally, code trong khối này được thực thi ngay cả khi có phát sinh ngoại lệ hay không. Khối này cơ bản để giải phóng các tài nguyên chiếm giữ.

int x = 10;
int y = 0;
int z = 0;
try {
    z = x / y;
}
catch (DivideByZeroException e1) {
    Console.WriteLine(e1.Message);
}
finally {
    // Luôn được thi hành dù có phát sinh ngoại lệ hay không
    Console.WriteLine(z);
}

Phát sinh ngoại lệ với throw

Nếu code của bạn muốn phát sinh ngoại lệ, khi muốn hệ thống biết có một lỗi nào đó cần xử lý, nếu không xử lý (bắt lại) thì chương trình kết thúc ở điểm phát sinh ngoại lệ. Để phát sinh ngoại lệ bạn cần tạo ra một đối tượng lớp Exception hoặc các lớp kế thừa từ nó, sau đó phát sinh bằng lệnh throw

public static double Thuong(double x, double y) {
    if (y == 0) {
        Exception myexception = new Exception("Số chia không được bằng 0");
        throw myexception;    // phát sinh ngoại lệ do số chia bằng 0.
    }
    return x / y;
}
static void Main(string[] args)
{
    double z = Thuong(100,0);
}

Khi chạy, ngoại lệ sẽ phát sinh, và ngoại lệ đó là myexception, chứa thông báo lỗi do bạn thiết lập. Do chương trình không bắt ngoại lệ này, nên nó dừng ngay lập tức

CS

Giờ muốn bắt chính ngoại lệ do bạn phát sinh

try {
    double z = Thuong(100,0);
}
catch (Exception e) {
    Console.WriteLine(e.Message);
}

Chạy, sẽ in ra dòng: "Số chia không được bằng 0"

Tạo Exeption riêng

Nếu muốn tạo ra các lớp để quẳng ra các lỗi khi cần thiết, thì chỉ việc kế thừa lớp Exception. Lợi ích việc tạo ra lớp riêng, nó giúp cho việc quản lý lỗi - gỡ rối tốt hơn.

Ví dụ, người dùng đưa vào một dữ liệu chuỗi string, chuỗi này phải có độ dài dưới 10 ký tự, nếu dài hơn thì phát sinh Exception riêng.

Tạo thử một lớp đặt tên là DataTooLongExeption như sau:

using System;
namespace CS15_Error
{
    public class DataTooLongExeption : Exception
    {
        const string erroMessage = "Dữ liệu quá dài";
        public DataTooLongExeption() : base(erroMessage) {
        }
    }
} 

Sử dụng nó để phát sinh ngoại lệ

using System;

namespace CS15_Error
{
    class Program
    {
        public static void UserInput(string  s) {
            if (s.Length > 10)
            {
                Exception e = new DataTooLongExeption();
                throw e;    // lỗi văng ra
            }
            //Other code - no exeption
        }
        static void Main(string[] args)a
        {
             try {
                 UserInput("Đây là một chuỗi rất dài ...");
             }
             catch (DataTooLongExeption e) {
                 Console.WriteLine(e.Message);
             }
             catch (Exception otherExeption) {
                 Console.WriteLine(otherExeption.Message);
             }


        }
    }
}

    
Đăng ký theo dõi ủng hộ kênh