Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Xử lý ngoại lệ (Exception) trong C#

Khái niệm

Ngoại lệ (Exception) là lỗi xảy ra tại runtime, làm gián đoạn luồng thực thi bình thường. C# xử lý ngoại lệ bằng 4 từ khóa: try, catch, finally, throw.

Cơ chế 4 từ khóa

Từ khóaChức năng
tryKhối mã có thể ném ngoại lệ. Bắt buộc theo sau bởi catch hoặc finally.
catchBắt và xử lý ngoại lệ cụ thể. Có thể có nhiều catch cho các loại exception khác nhau.
finallyKhối mã **luôn chạy** sau try/catch (dù có exception, return, hay không). Dùng cho cleanup.
throwNém ngoại lệ (tạo mới hoặc ném lại exception hiện tại).

Hệ thống phân cấp Exception

  • System.Exception - cơ sở tất cả ngoại lệ.
  • System.SystemException - ngoại lệ hệ thống (NullReference, DivideByZero, IndexOutOfRange...).
  • System.ApplicationException - base cho ngoại lệ ứng dụng ( ít dùng hiện nay, khuyến nghị kế thừa trực tiếp từ Exception).

Ví dụ 1: Try-catch-finally cơ bản

using System;

public class Demo
{
    int result = 0;

    public void Division(int num1, int num2)
    {
        try
        {
            result = num1 / num2;
        }
        catch (DivideByZeroException e)
        {
            Console.WriteLine($"Exception caught: {e.Message}");
        }
        finally
        {
            Console.WriteLine($"Result = {result}"); // Luôn chạy
        }
    }

    public static void Main(string[] args)
    {
        Demo d = new Demo();
        d.Division(100, 0);
    }
}

Kết quả

Exception caught: Attempted to divide by zero.
Result = 0

Ví dụ 2: Reflection với try-catch

using System;
using System.Reflection;

public class Demo
{
    public static void Main()
    {
        Type type = typeof(Subject);
        try
        {
            FieldInfo fieldInfo = type.GetField("SubName");
            MemberInfo[] info = type.GetMember("SubName");
            Console.Write("Members = ");
            for (int i = 0; i < info.Length; i++)
                Console.WriteLine($" {info[i]}");
            Console.WriteLine($"FieldInfo = {fieldInfo}");
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine($"Exception: {e.GetType().Name} - {e.Message}");
        }
    }
}

public class Subject
{
    public string SubName = "Science";
}

Kết quả

Members =  System.String SubName
FieldInfo = System.String SubName

Best Practices

  • Chỉ catch ngoại lệ bạn **có thể xử lý** được. Đừng catch Exception chung chung trừ khi log và re-throw.
  • Dùng throw; (không tham số) để ném lại exception gốc, bảo toàn stack trace.
  • Sử dụng using / IDisposable thay vì try/finally thủ công cho tài nguyên.
  • Tạo custom exception kế thừa từ Exception (không phải ApplicationException).
  • Tránh dùng exception cho control flow bình thường (performance).

Exception Filters (C# 6+)

try { ... }
catch (SqlException ex) when (ex.Number == 1205) // Deadlock
{
    // Retry logic
}
catch (SqlException ex) when (ex.Number == 2627) // Unique constraint
{
    // Handle duplicate
}