TOC

This article is currently in the process of being translated into Vietnamese (~82% done).

Advanced topics:

Exception handling

Trong mọi chương trình, có thể có lỗi. Với C#, chúng ta may mắn có một trình biên dịch tốt giúp chúng ta tránh một số lỗi. Rõ ràng nó không thể thấy mọi lỗi có thể xảy ra và trong các tình huốn này, .NET framework sẽ có ngoại lệ, để thông báo cho chúng ta cái gì đó đang sau. Trong phần đầu chương về mảng, tôi đã mô tả cách mà chúng ta có thể có ngoại lệ nếu chúng ta cố gắng lưu nhiều phần tử trong mảng. Ví dụ:

using System;
using System.Collections;

namespace ConsoleApplication1
{
    class Program
    {
static void Main(string[] args)
{
    int[] numbers = new int[2];

    numbers[0] = 23;
    numbers[1] = 32;
    numbers[2] = 42;

    foreach(int i in numbers)
Console.WriteLine(i);
    Console.ReadLine();
}
    }
}

Nào, thử chạy ví dụ này, và bạn sẽ thấy những gì tôi nói. Bạn có thấy có gì sai không? Chúng ta định nghĩa một mảng các số nguyên có kích thước hai phần tử và chúng ta cố dùng 3 vị trí. Rõ ràng, điều này gây lỗi khi bạn chạy. IDE sẽ cho chúng ta vài lựa chọn nhưng nếu bạn cứ chạy chương trình thì bạn sẽ bị lỗi. Nếu bạn biết một lỗi có thể xảy ra thì bạn có thể xử lý nó. Đây là lúc ngoại lệ được dùng, Chúng ta sửa lại:

int[] numbers = new int[2];
try
{
    numbers[0] = 23;
    numbers[1] = 32;
    numbers[2] = 42;

    foreach(int i in numbers)
Console.WriteLine(i);
}
catch
{
    Console.WriteLine("Something went wrong!");
}
Console.ReadLine();

Hãy để tôi chỉ cho bạn người bạn tốt nhất khi xử lý lỗi: try..catch. Thử chạy chương trình và theo dõi sự khác biệt - thay vì việc Visual Studio/Windows báo cho chúng ta có vấn đê nghiêm trọng xảy ra thì chúng ta tự làm. Nhưng có lẽ là tuyệt hơn nếu chúng ta có thể chỉ ra cái gì sau? Không vấn đề:

catch(Exception ex)
{
    Console.WriteLine("An error occured: " + ex.Message);
}

Như bạn thấy, chúng ta thêm vào một số thứ trong catch. Chúng ta hiển thị ngoại lệ có thể bắt được, trong trường hợp này là cơ bản của toàn bộ ngoại lệ, Exception Bằng cách đó, chúng ta lấy được thông tin về vấn đề gây ra ngoại lệ và đưa ra bằng thuộc tính Message, chúng ta đã mô tả được vấn đề.

Như đã nói, Exception là loại ngoại lệ tổng quát nhất. Nguyên tắc của xử lý ngoại lệ là chúng ta luôn dùng loại ngoại lệ ít tổng quát nhất, và trong trường hợp này chúng ta biết chính xác loại ngoại lệ trong chương trình. Bằng cách nào? Vì Visual Studio cho chúng ta biết khi chúng ta không xử lý. Nếu bạn băn khoăn thì tài liệu thường mô tả loại ngoại lệ mà phương thức có thể xuất ra. Một cách khác để tìm ngoại lệ là dùng lớp Exception - thay đổi đầu ra:

Console.WriteLine("An error occured: " + ex.GetType().ToString());

Như mong đợi thì kết quả là IndexOutOfRangeException. Chúng ta nên xử lý ngoại lệ này nhưng không gì ngăn chúng ta xử lý nhiều hơn một ngoại lệ. Trong vài trường hợp bạn có thể muốn làm khác đi tùy theo ngoại lệ nào được gọi. Chỉ đơn giản thay khối catch:

catch(IndexOutOfRangeException ex)
{
    Console.WriteLine("An index was out of range!");
}
catch(Exception ex)
{
    Console.WriteLine("Some sort of error occured: " + ex.Message);
}

Như bạn thấy, đầu tiên chúng ta tìm IndexOutOfRangeException. Chúng ta đi từ ngoại lệ chi tiết nhất.

Một điều nữa bạn cũng nên biết về exception là khối finally. Khối finally có thể được thêm vào khối catch, hay dùng độc nhất tùy vào nhu cầu. Khối finally luôn chạy - có hay không có ngoại lệ. Đó là khi bạn cần đóng file hay giải phóng đối tượng mà bạn không cần. Do ví dụ của chúng ta khá đơn giản nên chúng ta không cần giải phóng gì vì bộ thu thập rác đã làm điều đó. Nhưng khi vào tình huống cụ thể thì bạn cần khối finally, đây là một ví dụ:

int[] numbers = new int[2];
try
{
    numbers[0] = 23;
    numbers[1] = 32;
    numbers[2] = 42;

    foreach(int i in numbers)
Console.WriteLine(i);
}
catch(IndexOutOfRangeException ex)
{
    Console.WriteLine("An index was out of range!");
}
catch(Exception ex)
{
    Console.WriteLine("Some sort of error occured: " + ex.Message);
}
finally
{
    Console.WriteLine("It's the end of our try block. Time to clean up!");
}
Console.ReadLine();

Nếu bạn chạy chương trình, bạn sẽ thấy cả khối exception và khối finally được thực hiện. Nếu bạn bỏ đi dòng thêm số 42 thì chỉ khối finally chạy.

Another important part you should know about exceptions, is how they impact the method in which the exceptions occur. Not all unhandled exceptions are fatal for your application, but when they aren't, you should not expect the remaining code of the method to be executed. On the other hand, if you do handle the exception, only the lines after the try block will be executed. In our example, the loop that outputs the values of the array is never reached, because the try block goes straight to the catch/finally block(s) once an exception is thrown. However, the last line, where we read from the console to prevent the application from exiting immediately, is reached. You should always have this in mind when you construct try blocks.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!