2011-08-02 16 views
17

Ayúdenme amigos: ¿por qué este código causa una VerificationException cuando se ejecuta en .NET 4.0?¿Por qué esta línea causa una VerificationException cuando se ejecuta en .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; 
} 

me corrieron peverify en el ensamblado de .NET 2.0 y tiene el siguiente mensaje:

ImageResizer.Util.Utils :: parseEnum [T]] [Separar 0X0000000A] El 'esto' parámetro a la llamada debe ser el parámetro 'este' del método de llamada.

Esto provoca un mensaje VerificationException: Operation could destabilize the runtime al ejecutar el código bajo confianza media.

Ya he leído todas las publicaciones similares en el desbordamiento de pila, y ninguna de ellas se aplica a este código.

¿Hay algo nuevo en los genéricos que haga que este código no sea válido?

+0

Acabo de ejecutar este código y no recibí ninguna excepción. ¿Estás seguro de que aquí es donde yace el error? ¿Esto se está usando en asp? –

+0

¿Está generando el ensamblado de .NET usando Visual Studio u otro compilador (como Mono)? – Jacob

+1

El mensaje de error me indica que está en el sitio de la llamada (es decir, donde está llamando al método) que está teniendo este problema. ¿Puedes mostrarnos ese código también? –

Respuesta

31

El motivo subyacente del error es un cambio en la firma de IsEnum.

En .NET 2.0 (y 3.0), IsEnum wasn't a virtual method:

public bool IsEnum { get; } 

El conjunto emitida llamarlo es:

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

En .NET 4.0, IsEnum is a virtual method:

public virtual bool IsEnum { get; } 

Aquí está la misma línea de ensamblaje para 4.0:

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

El error que está recibiendo es added in peverify just before the 2.0 release, y advierte cuando se llama un método virtual de forma no virtual.

Ahora, peverify carga su código, carga .NET 4.0 y luego verifica su código. Como su código llama al método virtual (.NET 4.0) de forma no virtual, se muestra el error.

Uno pensaría que ya que está compilando contra la versión .NET 2.0, esto debería estar bien, y cargaría .NET 2.0 CLR para verificar. No parece así.

Editar:

Para comprobar esto, he descargado .NET 2.0's SDK y probamos el peverify allí. Verifica correctamente el código.

Así que el mensaje parece ser este: utilice un peverify que coincida con el marco de destino de su código.

Solución:

Parece que el _Type interface proporciona una solución a este:

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

La documentación dice que está diseñado para ser llamado desde el código no administrado, sino como un efecto secundario de la misma al ser una interfaz, proporciona un método estable (virtual) para llamar.

He confirmado que funciona con peverify si se dirige a 2.0 o 4.0.

+4

¡Fantástica respuesta! Me encanta aprender cosas como esta. –

+0

Gracias - tiene sentido. Mis ensamblados apuntan a los frameworks .NET 2.0 y .NET 4.0, así que supongo que simplemente no puedo llamar a IsEnum, ¿correcto? –

+1

En realidad, hay una interfaz '_Type' que dice que es" independiente de la versión ". Podría haber sido diseñado para solucionar problemas como este. Lo agregaré a la respuesta. – porges

Cuestiones relacionadas