2013-06-05 29 views
12

Khối trên đề cập đến một câu hỏi + câu trả lời khác về SO KHÔNG chứa câu trả lời đúng áp dụng ở đây!Có phải ngoại lệ chung được hỗ trợ bên trong bẫy không?

Tôi có phương pháp được sử dụng để kiểm tra đơn vị. Mục đích của phương pháp này là để đảm bảo rằng một đoạn mã (được tham chiếu bởi một đại biểu) sẽ ném một ngoại lệ cụ thể. Nếu ngoại lệ đó được ném, kiểm tra đơn vị thành công. Nếu không có ngoại lệ được ném hoặc loại ngoại lệ khác được ném, kiểm tra đơn vị sẽ thất bại.

/// <summary> 
/// Checks to make sure that the action throws a exception of type TException. 
/// </summary> 
/// <typeparam name="TException">The type of exception expected.</typeparam> 
/// <param name="action">The code to execute which is expected to generate the exception.</param> 
public static void Throws<TException>(Action action) 
    where TException : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (TException) 
    { 
     return; 
    } 
    catch (Exception ex) 
    { 
     Assert.Fail("Wrong exception was thrown. Exception of type " + ex.GetType() + " was thrown, exception of type " + typeof(TException) + " was expected."); 
    } 
    Assert.Fail("No exception was thrown. Exception of type " + typeof(TException) + " was expected."); 
} 

Các cuộc gọi tiếp theo nên thành công, nhưng nó không thành công:

int result = 0; 
Throws<DivideByZeroException>(() => result = result/result); 

Khi ngoại lệ dự kiến ​​của loại TException được ném, nó luôn luôn bị bắt bởi đánh bắt thứ hai, không phải do bắt đầu. Tại sao điều này?

Tất nhiên tôi có thể sử dụng một workarround với một bắt và kiểm tra nếu ex là loại TException. Bởi tôi chỉ đơn giản muốn biết/hiểu tại sao mã này biên dịch nhưng công việc đơn giản (không bao giờ?).

EDIT

Theo yêu cầu của một "làm việc" demo:

using System; 

namespace GenericExceptionDemo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int n = 0; 
      Catch<DivideByZeroException>(() => n = n/n); 
     } 

     static public void Catch<TException>(Action action) 
      where TException: Exception 
     { 
      try 
      { 
       action(); 
       Console.WriteLine("No exception thrown. !!!Fail!!!"); 
      } 
      catch (TException) 
      { 
       Console.WriteLine("Expected exception thrown. PASS!"); 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine("An unexpected exception of type " + ex.GetType() + " thrown. !!!FAIL!!!"); 
      } 
     } 
    } 
} 
+7

Bạn đang sử dụng khung kiểm tra đơn vị nào? Hầu hết đã có 'Assert.Throws' ... –

+8

Mã của bạn hoạt động cho tôi ... vui lòng hiển thị một chương trình ngắn nhưng đầy đủ để minh họa sự cố. –

+0

Tại sao nói rằng một loại ngoại lệ sai được ném? Có thể .Net framework tự ném cho bạn một System.Drawing.Exception khi bạn đang làm việc với GUI? –

Trả lời

2

Bạn không phải là người đầu tiên gặp phải vấn đề này. This question rất giống nhau. Nếu bạn khai thác thông qua các câu trả lời và các liên kết, nó đi xuống đến một lỗi trong CLR.

EDIT: Là một Martin theo dõi, tôi đã chạy ví dụ từ VS2010 và bị kết quả như sau:

  • Nhắm mục tiêu NET 4, PASS
  • Nhắm mục tiêu NET 3.5, FAIL
  • Nhắm mục tiêu .NET 3.5 trong chế độ RELEASE, PASS

Đáng buồn thay, tất cả các liên kết SO tới Báo cáo lỗi Microsoft đều đã chết và tôi không thể tìm thấy bất kỳ liên kết nào khác.

+1

Câu hỏi trước đó đã được trả lời trong năm 2009, liệu nó vẫn được áp dụng? –

+0

Câu hỏi hay. Tôi chỉ cần đặt mã của Martin trong VS (với các chỉnh nhỏ). Nếu tôi nhắm mục tiêu .NET 4, mã hoạt động như mong đợi. Nếu tôi nhắm mục tiêu 3,5, tôi thấy hành vi kỳ quặc mà Martin mô tả. –

+0

Nó không áp dụng. Cả hai câu hỏi đều giống nhau, nhưng câu hỏi khác có một biến ngoại lệ bổ sung 'tex', và câu trả lời (đúng) là loại bỏ biến đó. Trong trường hợp của tôi, tôi không sử dụng một biến, để câu trả lời không thể áp dụng cho tình huống này. –

0

(Đây không phải là một câu trả lời cụ thể;. Nhưng tôi không thể đăng nó như là một lời nhận xét quá)

tôi không thể tái sản xuất này (VS 2012, .NET 4.5, C# 5.0, mỗi SP được cài đặt).

tôi định nghĩa lớp này ngoại lệ:

class MyException : Exception 
{ 
    public MyException() { } 
    public MyException(string message) : base(message) { } 
} 

và một phương pháp:

static void Throws<T>(Action action) where T : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (T) { Console.WriteLine("got {0}", typeof(T)); } 
    catch (Exception) { Console.WriteLine("got Exception"); } 
} 

và tôi đã thử nghiệm nó theo cách này:

Throws<MyException>(() => { throw new MyException(); }); 

int result = 0; 
Throws<DivideByZeroException>(() => result = result/result); 

và đầu ra là:

  • có Draft.MyException
  • có Hệ thống.DivideByZeroException

Vì vậy, (IMHO) bạn nên tìm một nơi khác.

Các vấn đề liên quan