Tìm hiểu C# và ứng dụng của C# p 14

Chia sẻ: Yukogaru | Ngày: | Loại File: PDF | Số trang:7

0
52
lượt xem
6
download

Tìm hiểu C# và ứng dụng của C# p 14

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang 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...

Chủ đề:
Lưu

Nội dung Text: Tìm hiểu C# và ứng dụng của C# p 14

  1. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang 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; namespace Programming_CSharp { public class Test { public static void Main( ) { Test t = new Test( ); t.TestFunc( ); } public void TestFunc( ) { try { Console.WriteLine("Open file here"); double a = 12; double b = 0; Console.WriteLine ("{0} / {1} = {2}", a, b, DoDivide(a,b)); Console.WriteLine ("This line may or may not print"); } catch (System.DivideByZeroException e) { Console.WriteLine( "\nDivideByZeroException! Msg: {0}", e.Message); Console.WriteLine("\nHelpLink: {0}", e.HelpLink); Console.WriteLine( "\nHere's a stack trace: {0}\n", e.StackTrace); } catch 80
  2. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang { 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 = "http://www.libertyassociates.com"; 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: http://www.libertyassociates.com Here's a stack trace: at Programming_CSharp.Test.DoDivide(Double a, Double b) in c:\...exception06.cs:line 56 at Programming_CSharp.Test.TestFunc( ) in...exception06.cs:line 22 Close file here. Kết quả liệt kê các phương thức theo trình tự ngược với trình tự chúng được gọi. Đọc kết quả trên như sau: Có một biệt lệ xảy ra tại hàm DoDivide(), hàm DoDivide này được gọi bởi hàm TestFunc(). Trong ví dụ này ta tạo một thể hiện của DivideByZeroException DivideByZeroException e = new DivideByZeroException(); Do không truyền tham số, thông báo mặc định được dùng: DivideByZeroException! Msg: Attempted to divide by zero. Ta có thể thay thông báo mặc định này bằng cách truyền tham số khi khởi tạo: new DivideByZeroException( "You tried to divide by zero which is not meaningful"); Trong trường hợp này kết quả sẽ là: DivideByZeroException! Msg:You tried to divide by zero which is not meaningful Trước khi ném biệt lệ này, ta thiết đặt thuộc tính HelpLink e.HelpLink = "http://www.libertyassociates.com"; Khi biệt lệ được bắt, chương trình in thông báo và cả đường dẫn đến kết nối giúp đỡ catch (System.DivideByZeroException e) 81
  3. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang { 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( ) { Test t = new Test( ); t.TestFunc( ); } public void TestFunc( ) { try { Console.WriteLine("Open file here"); double a = 0; double b = 5; Console.WriteLine("{0}/{1}={2}", a, b, DoDivide(a,b)); Console.WriteLine("This line may or may not print"); } catch (System.DivideByZeroException e) { Console.WriteLine("\nDivideByZeroException! Msg: {0}", e.Message); Console.WriteLine("\nHelpLink: {0}\n", e.HelpLink); } catch (MyCustomException e) { Console.WriteLine("\nMyCustomException! Msg: {0}", e.Message); Console.WriteLine("\nHelpLink: {0}\n", e.HelpLink); 82
  4. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang } catch { Console.WriteLine("Unknown exception caught"); } 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 = "http://www.libertyassociates.com"; throw e; } if (a == 0) { MyCustomException e = new MyCustomException( "Can't have zero divisor"); e.HelpLink = "http://www.libertyassociates.com/NoZeroDivisor.htm"; throw e; } return a / b; } } } MyCustomException thừa kế từ System.ApplicationException và nó không có gì khác hơn là một hàm dựng nhận tham số là một thông báo. Câu thông báo này sẽ được chuyển tới lớp cha. Biệt lệ MyCustomException được thiết kế cho chính lớp Test, không cho phép chia cho 0 và không chia 0 cho số khác. Sử dụng ArithmeticException cũng cho kết quả tương tự nhưng có thể gây nhầm lẫn cho lập trình viên khác do phép chia 0 cho một số không phải là một lỗi toán học. 11.4 Ném biệt lệ lần nữa. Sẽ có trường hợp ta muốn rằng trong khối lệnh catch ta sẽ khởi động một hành động sửa lỗi, và sau đó ném biệt lệ cho khối try khác (khối try của hàm gọi). Biệt lệ này có thể cùng loại hay khác loại với biệt lệ khối catch bắt được. Nếu là cùng loại, khối catch sẽ ném biệt lệ này một lần nữa; còn nếu khác loại, ta sẽ nhúng biệt lệ cũ vào biệt lệ mới để khối try 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ệ. 83
  5. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang 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(); } public void TestFunc() { try { DangerousFunc1(); } // khi bắt được biệt lệ tự tạo // in lịch sử các biệt lệ catch (MyCustomException e) { Console.WriteLine("\n{0}", e.Message); Console.WriteLine("Retrieving exception history..."); Exception inner = e.InnerException; while (inner != null) { Console.WriteLine("{0}",inner.Message); inner = inner.InnerException; } } } public void DangerousFunc1( ) { try { DangerousFunc2( ); } // nếu bắt được một biệt lệ // ném một biệt lệ tự tạo catch(System.Exception e) { MyCustomException ex = new MyCustomException( "E3 - Custom Exception Situation!",e); throw ex; } } public void DangerousFunc2( ) { try 84
  6. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang { 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) { throw; } catch (System.Exception) { Console.WriteLine("Exception handled here."); } } public void DangerousFunc4( ) { throw new DivideByZeroException( "E1 - DivideByZero Exception"); } } } Kết quả: E3 - Custom Exception Situation! Retrieving exception history... E2 - Func2 caught divide by zero E1 - DivideByZeroException Ghi chú: Kết quả xuất hiện trên màn hình không đủ để thể hiện hết ý, cách tốt nhất là nên chạy chương trình ở chế độ từng dòng lệnh để hiểu rõ vấn đề hơn. Chúng ta bắt đầu bằng lời gọi hàm DangerousFunc1() trong khối try try { DangerousFunc1( ); } 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. 85
  7. Quản lý lỗi Gvhd: Nguyễn Tấn Trần Minh Khang 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. catch (System.ArithmeticException) { throw; } Cú pháp trên ném cùng một loại biệt lệ cho khối try bên ngoài (chỉ cần từ khóa throw) DangerousFunc2() sẽ bắt được biệt lệ này, nó sẽ ném ra một biệt lệ mới thuộc kiểu Exception. Khi khởi tạo biệt lệ này, ta truyền cho nó hai tham số: thông báo E2 - Func2 caught divide by zero, và biệt lệ cũ để làm biệt lệ nội. DangerousFunc1() bắt biệt lệ này, làm vài công việc nào đó, sau đó tạo một biệt lệ có kiểu MyCustomException. Tương tự như trên khi khởi tạo biệt lệ ta truyền cho nó hai tham số: thông báo E3 - Custom Exception Situation!, và biệt lệ vừa bắt được làm biệt lệ nội. Đến thời điểm này biệt lệ đã có hai mức biệt lệ nội. Cuối cùng, khối catch sẽ bắt biệt lệ này và in thông báo E3 - Custom Exception Situation! Sau đó sẽ tiếp tục in các thông báo của các biệt lệ nội while (inner != null) { Console.WriteLine("{0}",inner.Message); inner = inner.InnerException; } Và ta có kết quả Retrieving exception history... E2 - Func2 caught divide by zero E1 - DivideByZero Exception 86
Đồng bộ tài khoản