Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang
80
11.2 Đối tượng Exception
Đối tượng
System.Exception
cung cấp nhiều phương thức và property hữu ích
cho việc bẫy lỗi. Chẳng hạn property
Message
cung cấp thông tin tại sao nó được
ném.
Message
là thuộc tính chỉ đọc, nó được thiết đặt vào lúc khởi tạo biệt lệ.
Property
HelpLink
cung cấp một kết nối đến tập tin giúp đỡ. Property này có thể
đọc và thiết đặt. Property
StackTrace
chỉ đọc và được thiết lập vào lúc chạy.
Trong ví dụ 11-6, property
Exception.HelpLink
được thiết đặt và nhận về để
thông tin thêm cho người dùng về biệt lệ
DivideByZeroException
. Property
StackTrace
được dùng để cung cấp các vết của vùng nhớ
stack
. Nó hiển thị
hàng loạt các phương thức đã gọi dẫn đến phương thức mà biệt lệ được ném ra.
Ví dụ 11-6. Làm việc với đối tượng Exception
using System;
81
{
Console.WriteLine("Unknown exception caught");
}
finally
{
Console.WriteLine ("Close file here.");
}
}
public double DoDivide(double a, double b)
{
if (b == 0)
{
DivideByZeroException e = new DivideByZeroException();
e.HelpLink = "";
throw e;
}
if (a == 0)
throw new ArithmeticException( );
return a / b;
}
}
}
Kết quả:
Open file here
DivideByZeroException! Msg: Attempted to divide by zero.
HelpLink:
Here's a stack trace:
at Programming_CSharp.Test.DoDivide(Double a, Double b)
in c:\ exception06.cs:line 56
82
{
Console.WriteLine("\nDivideByZeroException! Msg: {0}",
e.Message);
Console.WriteLine("\nHelpLink: {0}", e.HelpLink);
Nhờ vậy ta có thể cung cấp các thông tin cần thiết cho người dùng. Sau đó là in
StackTrace
Console.WriteLine("\nHere's a stack trace:{0}", e.StackTrace);
Ta có kết quả cuối cùng.
11.3 Các biệt lệ tự tạo
Với các biệt lệ có thể tùy biến thông báo do CLR cung cấp, thường đủ cho hầu hết
các ứng dụng. Tuy nhiên sẽ có lúc ta muốn thêm nhiều dạng thông tin hơn cho đối
tượng biệt lệ, khi đó ta phải tự tạo lấy các biệt lệ mong muốn. Biệt lệ tự tạo bắt buộc
thừa kế từ lớp
System.Exception. Ví dụ 11-7 mô tả cách tạo một biệt lệ mới.
Ví dụ 11-7. Tự tạo biệt lệ
using System;
namespace Programming_CSharp
{
public class MyCustomException : System.ApplicationException
{
public MyCustomException(string message) : base(message)
{
}
}
public class Test
{
public static void Main( )
{
}
finally
{
Console.WriteLine ("Close file here.");
}
}
// do the division if legal
public double DoDivide(double a, double b)
{
if (b == 0)
{
DivideByZeroException e = new DivideByZeroException();
e.HelpLink = "";
throw e;
}
if (a == 0)
{
MyCustomException e = new MyCustomException(
"Can't have zero divisor");
e.HelpLink =
"
throw e;
}
return a / b;
}
}
}
MyCustomException
thừa kế từ
System.ApplicationException
hàm gọi biết được lịch sử của biệt lệ. Property
InnerException
được dủng để thực hiện việc này. Biệt lệ đem nhúng gọi là biệt
lệ nội.
Bởi vì
InnerException
cũng chính là một biệt lệ nên nó cũng có
InnerException
của nó. Cứ như vậy tạo nên một loạt các biệt lệ.
Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang
84
Ví dụ 11-8. Ném biệt lệ lần nữa và biệt lệ nội (inner exception)
using System;
namespace Programming_CSharp
{
public class MyCustomException : System.Exception
{
public MyCustomException(string message,Exception inner):
base(message,inner)
{
}
}
public class Test
{
public static void Main()
{
Test t = new Test();
t.TestFunc();
}
MyCustomException ex = new MyCustomException(
"E3 - Custom Exception Situation!",e);
throw ex;
}
}
public void DangerousFunc2( )
{
try
Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang
85
{
DangerousFunc3( );
}
// nếu bắt được biệt lệ DivideByZeroException thực hiện
// vài công việc sữa lỗi và ném ra biệt lệ tổng quát
catch (System.DivideByZeroException e)
{
Exception ex = new Exception(
"E2 - Func2 caught divide by zero",e);
throw ex;
}
}
public void DangerousFunc3( )
{
try
{
DangerousFunc4( );
}
catch (System.ArithmeticException)
{
}
DangerousFunc1()
gọi
DangerousFunc2()
,
DangerousFunc2()
gọi
DangerousFunc3(), DangerousFunc3()
gọi
DangerousFunc4()
. Tất cả
các lời gọi này đều có khối
try
của riêng nó. Cuối cùng
DangerousFunc4()
ném
một biệt lệ
DivideByZeroException
với câu thông báo
E1 - DivideByZero
Exception
.
Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang
86
Khối lệnh catch trong hàm DangerousFunc3() sẽ bắt biệt lệ này. Theo logic, tất
cả các lỗi toán học đều được bắt bởi biệt lệ
ArithmeticException
(vì vậy cả
DivideByZeroException
). Nó chẳng làm gì, chỉ ném biệt lệ này lần nữa.
inner = inner.InnerException;
}
Và ta có kết quả
Retrieving exception history
E2 - Func2 caught divide by zero
E1 - DivideByZero Exception