net - remarks c#
¿Por qué esta línea causa una VerificationException cuando se ejecuta en.NET 4? (1)
Ayúdame gente: ¿por qué este código causa una VerificationException cuando se ejecuta en .NET 4.0?
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;
}
peverify
en el ensamblado .net 2.0 y recibí el siguiente mensaje:
ImageResizer.Util.Utils :: parseEnum [T]] [offset 0x0000000A] El parámetro ''this'' para la llamada debe ser el parámetro ''this'' del método de llamada.
Esto provoca una VerificationException: Operation could destabilize the runtime
mensaje de VerificationException: Operation could destabilize the runtime
cuando se ejecuta el código bajo la confianza media.
Ya leí todas las publicaciones similares en 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 sea inválido de algún modo?
El motivo subyacente del error es un cambio en la firma de IsEnum.
En .NET 2.0 (y 3.0), IsEnum no era un método virtual :
public bool IsEnum { get; }
El conjunto emitido para llamarlo es:
call instance bool [mscorlib]System.Type::get_IsEnum()
En .NET 4.0, IsEnum es un método virtual :
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á obteniendo se agregó en peverify justo antes de la versión 2.0 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 podría pensar que dado que está compilando contra la versión .NET 2.0, esto debería estar bien, y cargaría el CLR de .NET 2.0 para verificar. No parece así.
Editar:
Para comprobar esto, descargué el SDK de .NET 2.0 y probé el peverify
allí. Verifica correctamente el código.
Entonces, el mensaje parece ser el siguiente: use un peverify
que coincida con el marco de destino de su código.
Solución:
Parece que la interfaz _Type
proporciona una solución a esto:
if (((_Type)typeof(T)).IsEnum) ...
La documentación dice que está diseñado para ser llamado desde un código no administrado, pero como un efecto secundario de que es una interfaz, proporciona un método estable (virtual) para llamar.
He confirmado que funciona con peverify
si tiene como objetivo 2.0 o 4.0.