2011-08-02 20 views
17

Giúp tôi với mọi người - tại sao mã này lại gây ra một lỗi xác minh khi chạy dưới .NET 4.0?Tại sao dòng này gây ra một ExceptionException khi chạy dưới .NET 4?

public T parseEnum<T>(string value, T defaultValue) { 
    //Removing the following lines fixes the problem 
    if (!typeof(T).IsEnum) throw new ArgumentException("T must be an enumerated type"); 
    return defaultValue; 
} 

Tôi chạy peverify trên lắp ráp .net 2.0 và đã được thông báo sau:

ImageResizer.Util.Utils :: parseEnum [T]] [bù đắp 0x0000000A] Các 'này' tham số để cuộc gọi phải là tham số 'this' của phương thức gọi.

Điều này gây ra thông báo VerificationException: Operation could destabilize the runtime khi chạy mã dưới sự tin tưởng trung bình.

Tôi đã đọc tất cả các bài đăng trông giống nhau trên ngăn xếp ngăn xếp và không ai trong số chúng áp dụng cho mã này.

Có điều gì mới mẻ với generics có thể khiến mã này không hợp lệ không?

+0

Tôi vừa chạy mã này và không nhận được ngoại lệ như vậy. Bạn có chắc đây là nơi có lỗi không? Đây có phải là được sử dụng trong asp? –

+0

Bạn có đang tạo assembly .NET bằng Visual Studio hay trình biên dịch khác (như Mono) không? – Jacob

+1

Thông báo lỗi cho tôi biết rằng nó đang ở trang cuộc gọi (tức là nơi bạn đang gọi phương thức) đang gặp sự cố này. Bạn có thể cho chúng tôi thấy mã đó không? –

Trả lời

31

Lý do cơ bản của lỗi là thay đổi trong chữ ký của IsEnum.

Trong .NET 2.0 (và 3.0), IsEnum wasn't a virtual method:

public bool IsEnum { get; } 

Việc lắp ráp phát ra để gọi nó là:

call instance bool [mscorlib]System.Type::get_IsEnum() 

Trong .NET 4.0, IsEnum is a virtual method:

public virtual bool IsEnum { get; } 

Đây là cùng một dòng lắp ráp cho 4.0:

callvirt instance bool [mscorlib]System.Type::get_IsEnum() 

Lỗi bạn nhận được là added in peverify just before the 2.0 release và cảnh báo khi phương thức ảo được gọi là không thực sự.

Bây giờ, peverify tải lên mã của bạn, tải .NET 4.0 và sau đó kiểm tra mã của bạn. Vì mã của bạn gọi phương thức ảo (.NET 4.0) không thực sự, lỗi được hiển thị.

Người ta sẽ nghĩ rằng vì bạn đang xây dựng dựa trên phiên bản .NET 2.0, điều này sẽ ổn, và nó sẽ tải .NET 2.0 CLR để kiểm tra. Nó không có vẻ như vậy.

Edit:

Để kiểm tra điều này, tôi đã tải về .NET 2.0's SDK và thử peverify trong đó. Nó xác minh chính xác mã.

Vì vậy, thông báo có vẻ như thế này: sử dụng peverify phù hợp với khung mục tiêu của mã của bạn.

Giải pháp:

Dường như _Type interface cung cấp một giải pháp cho điều này:

if (((_Type)typeof(T)).IsEnum) ... 

Các tài liệu cho biết nó được thiết kế để được gọi là từ mã không được quản lý, nhưng là một tác dụng phụ của nó là một giao diện, nó cung cấp một phương thức ổn định (ảo) để gọi.

Tôi đã xác nhận rằng nó hoạt động với peverify cho dù bạn nhắm mục tiêu 2.0 hoặc 4.0.

+4

Câu trả lời tuyệt vời! Tôi thích học những thứ như thế này. –

+0

Cảm ơn - nó có ý nghĩa. Hội đồng của tôi đang nhắm mục tiêu cả hai khuôn khổ .NET 2.0 và .NET 4.0, vì vậy tôi đoán tôi chỉ đơn giản là không thể gọi IsEnum, đúng không? –

+1

Trên thực tế, có giao diện '_Type' cho biết đó là" phiên bản độc lập ". Nó có thể đã được thiết kế để giải quyết các vấn đề như thế này. Tôi sẽ thêm nó vào câu trả lời. – porges

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