2011-08-02 8 views
17

Pomóżcie mi - dlaczego ten kod wywołuje wyjątek VerificationException po uruchomieniu w .NET 4.0?Dlaczego ta linia powoduje wyjątek VerificationException podczas działania w środowisku .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; 
} 

Pobiegłem peverify na zespole .net 2.0 i mam następujący komunikat:

ImageResizer.Util.Utils :: parseEnum [T]] [offset 0x0000000A] do 'tego' parametru do wywołanie musi być parametrem "ten" metody wywołującej.

Powoduje to, że podczas uruchamiania kodu pod średnim zaufaniem pojawia się komunikat VerificationException: Operation could destabilize the runtime.

Przeczytałem już wszystkie podobne, wyglądające posty na przepełnieniu stosu i żadne z nich nie ma zastosowania do tego kodu.

Czy jest coś nowego w przypadku leków generycznych, które spowodowałyby, że kod ten byłby w jakiś sposób nieprawidłowy?

+0

Po prostu uruchomiłem ten kod i nie otrzymałem takiego wyjątku. Jesteś pewien, że to jest błąd? Czy to jest używane w asp? –

+0

Czy generujesz zestaw .NET za pomocą programu Visual Studio lub innego kompilatora (np. Mono)? – Jacob

+1

Komunikat o błędzie wskazuje, że znajduje się on na stronie wywołania (tj. W miejscu, w którym wywoływana jest metoda), która ma ten problem. Czy możesz nam pokazać ten kod? –

Odpowiedz

31

Podstawową przyczyną błędu jest zmiana w sygnaturze IsEnum.

W NET (2.0 i 3.0), IsEnum wasn't a virtual method:

public bool IsEnum { get; } 

Zespół emitowane nazywać się:

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

W NET 4.0, IsEnum is a virtual method:

public virtual bool IsEnum { get; } 

Oto ta sama linia składania dla wersji 4.0:

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

Błąd, który otrzymujesz, to added in peverify just before the 2.0 release i ostrzega, gdy wirtualna metoda jest nazywana wirtualnie.

Teraz, peverify ładuje twój kod, ładuje .NET 4.0, a następnie sprawdza twój kod. Ponieważ twój kod wywołuje wirtualną metodę (.NET 4.0) w sposób inny niż wirtualny, pojawia się błąd.

Można by pomyśleć, że skoro budujesz z wersją .NET 2.0, powinno to być w porządku, a to by ładowało .NET 2.0 CLR by sprawdzić. Nie wydaje się tak.

Edit:

W celu sprawdzenia tego, Pobrałem .NET 2.0's SDK i próbował peverify tam. Poprawnie weryfikuje kod.

Tak więc wiadomość wyglądałaby tak: użyj peverify, która pasuje do docelowej struktury twojego kodu.

Rozwiązanie:

Wydaje się, że _Type interface dostarcza rozwiązania do tego:

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

Dokumentacja mówi, że jest przeznaczony do wywoływana z niezarządzanego kodu, ale jako efekt uboczny tego będąc interfejsem, zapewnia stabilną (wirtualną) metodę wywoływania.

Potwierdziłem, że działa z peverify niezależnie od tego, czy celujesz w wersji 2.0, czy 4.0.

+4

Fantastyczna odpowiedź! Uwielbiam się uczyć takich rzeczy. –

+0

Dzięki - ma to sens. Moje złoenia są ukierunkowane zarówno na platformy .NET 2.0, jak i .NET 4.0, więc domyślam się, że po prostu nie mogę wywołać IsEnum, prawda? –

+1

W rzeczywistości istnieje interfejs '_Type', który mówi, że jest" niezależny od wersji ". Być może został zaprojektowany, aby obejść takie problemy. Dodam to do odpowiedzi. – porges

Powiązane problemy