una que objeto metodos estructuras estructura ejemplos ejemplo datos clases clase c# optimization compiler-construction casting struct

metodos - que es un objeto en c#



C#''es'' verificación de tipo en struct-comportamiento de optimización de.NET 4.0 x86 impar (6)

Aparte de unos pocos nudos, el reflector indica que las únicas diferencias están en el método IsGuid:

DEPURAR:

.method public hidebysig static bool IsGuid(object item) cil managed { .maxstack 2 .locals init ( [0] bool CS$1$0000) L_0000: nop L_0001: ldarg.0 L_0002: isinst [mscorlib]System.Guid L_0007: ldnull L_0008: cgt.un L_000a: stloc.0 L_000b: br.s L_000d L_000d: ldloc.0 L_000e: ret }

LANZAMIENTO:

.method public hidebysig static bool IsGuid(object item) cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: isinst [mscorlib]System.Guid L_0006: ldnull L_0007: cgt.un L_0009: ret }

No soy lo suficientemente fluido para explicar estas diferencias, pero esta es una respuesta wiki de la comunidad así que tal vez alguien más pueda iluminarnos.

Cambiar el método para hacerlo genérico funciona alrededor de esto (¿posible error?)

public static bool IsGuid<T>(T item) { return item is Guid; }

Al igual que forzarlo a una variable local (pero debe usarse en el método para evitar que las optimizaciones entren en juego):

public static bool IsGuid(object item) { bool a = item is Guid; a.ToString(); return a; }

Actualización: he presentado un informe de error con Microsoft Connect, ¡vota por él!

Actualización 2: Microsoft marcó el informe de error como arreglado

Publicado por Microsoft el 18/08/2010 a las 17:25

Este error se solucionará en una versión futura del tiempo de ejecución. Me temo que es demasiado pronto para decir si estará en un paquete de servicio o en la próxima versión principal.

Desde que actualicé a VS2010 estoy obteniendo un comportamiento muy extraño con la palabra clave ''es''.

El programa a continuación (test.cs) muestra True cuando se compila en modo de depuración (para x86) y False cuando se compila con optimizaciones en (para x86). La compilación de todas las combinaciones en x64 o AnyCPU da el resultado esperado, True.

Todas las combinaciones de compilación bajo .NET 3.5 dan el resultado esperado, True.

Estoy usando el archivo por lotes a continuación (runtest.bat) para compilar y probar el código usando varias combinaciones del compilador .NET framework.

  • ¿Alguien más ha visto este tipo de problemas bajo .NET 4.0?
  • ¿Todos los demás ven el mismo comportamiento que yo en su computadora cuando ejecutan runtests.bat?
  • @ $ @ # $ ??

  • ¿Hay una solución para esto?

test.cs

using System; public class Program { public static bool IsGuid(object item) { return item is Guid; } public static void Main() { Console.Write(IsGuid(Guid.NewGuid())); } }

runtest.bat

@echo off rem Usage: rem runtest -- runs with csc.exe x86 .NET 4.0 rem runtest 64 -- runs with csc.exe x64 .NET 4.0 rem runtest v3.5 -- runs with csc.exe x86 .NET 3.5 rem runtest v3.5 64 -- runs with csc.exe x64 .NET 3.5 set version=v4.0.30319 set platform=Framework for %%a in (%*) do ( if "%%a" == "64" (set platform=Framework64) if "%%a" == "v3.5" (set version=v3.5) ) echo Compiler: %platform%/%version%/csc.exe set csc="C:/Windows/Microsoft.NET/%platform%/%version%/csc.exe" set make=%csc% /nologo /nowarn:1607 test.cs rem CS1607: Referenced assembly targets a different processor rem This happens if you compile for x64 using csc32, or x86 using csc64 %make% /platform:x86 test.exe echo =^> x86 %make% /platform:x86 /optimize test.exe echo =^> x86 (Optimized) %make% /platform:x86 /debug test.exe echo =^> x86 (Debug) %make% /platform:x86 /debug /optimize test.exe echo =^> x86 (Debug + Optimized) %make% /platform:x64 test.exe echo =^> x64 %make% /platform:x64 /optimize test.exe echo =^> x64 (Optimized) %make% /platform:x64 /debug test.exe echo =^> x64 (Debug) %make% /platform:x64 /debug /optimize test.exe echo =^> x64 (Debug + Optimized) %make% /platform:AnyCPU test.exe echo =^> AnyCPU %make% /platform:AnyCPU /optimize test.exe echo =^> AnyCPU (Optimized) %make% /platform:AnyCPU /debug test.exe echo =^> AnyCPU (Debug) %make% /platform:AnyCPU /debug /optimize test.exe echo =^> AnyCPU (Debug + Optimized)

Resultados de la prueba

Cuando ejecuto el archivo runtest.bat, obtengo los siguientes resultados en mi instalación de Win7 x64.

> runtest 32 v4.0 Compiler: Framework/v4.0.30319/csc.exe False => x86 False => x86 (Optimized) True => x86 (Debug) False => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 64 v4.0 Compiler: Framework64/v4.0.30319/csc.exe False => x86 False => x86 (Optimized) True => x86 (Debug) False => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 32 v3.5 Compiler: Framework/v3.5/csc.exe True => x86 True => x86 (Optimized) True => x86 (Debug) True => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized) > runtest 64 v3.5 Compiler: Framework64/v3.5/csc.exe True => x86 True => x86 (Optimized) True => x86 (Debug) True => x86 (Debug + Optimized) True => x64 True => x64 (Optimized) True => x64 (Debug) True => x64 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized)

tl; dr


Aquí están mis resultados en XP SP3 (x86):

>runtest Compiler: Framework/v4.0.30319/csc.exe False => x86 False => x86 (Optimized) True => x86 (Debug) False => x86 (Debug + Optimized) False => AnyCPU False => AnyCPU (Optimized) True => AnyCPU (Debug) False => AnyCPU (Debug + Optimized) >runtest v3.5 Compiler: Framework/v3.5/csc.exe True => x86 True => x86 (Optimized) True => x86 (Debug) True => x86 (Debug + Optimized) True => AnyCPU True => AnyCPU (Optimized) True => AnyCPU (Debug) True => AnyCPU (Debug + Optimized)

El punto interesante sobre este resultado es que el objetivo .NET 4 falla en AnyCPU (ejecutándose como x86) pero funciona en AnyCPU (ejecutándose como x64).


Curiosamente, esto funciona correctamente:

using System; public class Program { public static bool IsGuid(object item) { return item is Guid; } public static void Main() { Guid s = Guid.NewGuid(); Console.Write(IsGuid(s)); } }

Aquí está la diferencia en el il:

.method public hidebysig static void Main() cil managed { .entrypoint // Code size 23 (0x17) .maxstack 1 .locals init (valuetype [mscorlib]System.Guid V_0) IL_0000: call valuetype [mscorlib]System.Guid [mscorlib]System.Guid::NewGuid() IL_0005: stloc.0 IL_0006: ldloc.0 IL_0007: box [mscorlib]System.Guid IL_000c: call bool Program::IsGuid(object) IL_0011: call void [mscorlib]System.Console::Write(bool) IL_0016: ret } // end of method Program::Main


Desarrollé un ejemplo similar que falla de la misma manera:

using System; using System.Runtime.CompilerServices; public class Program { static void Main() { Console.Write(Verify(Test.Create())); Console.ReadLine(); } //[MethodImpl(MethodImplOptions.NoInlining)] static bool Verify(IDisposable item) { return item is Test; } struct Test : IDisposable { public void Dispose() { } public static Test Create() { return new Test(); } } }

Es un error del optimizador JIT. No puedo ponerle el dedo encima, optimiza mucho el código. Pero me parece que se mete en problemas cuando optimiza la conversión de boxeo. Error bastante serio, francamente.

Este error ha sido reparado, ya no puedo reproducirlo. Mi versión actual de clrjit.dll es 4.0.30319.237 con fecha del 17 de mayo de 2011. No puedo decir exactamente qué actualización lo reparó. Recibí una actualización de seguridad el 5 de agosto de 2011 que actualizaba clrjit.dll a la revisión 235 con una fecha del 12 de abril, que sería la más temprana.


Eso no es cool. Creo que deberías presentar un error. (connect.microsoft.com)

Además, esto parece funcionar (sin embargo, solo probé su falla):

public static bool IsGuid(object item) { return item.GetType() == typeof(Guid); }


Para responder a su última pregunta, puede agregar el atributo MethodImpl con la opción MethodImplOptions.NoInlining a su método IsGuid como una solución para solucionar el problema.

Acabo de hacer una prueba simple de cambiar entre la configuración de Debug y Release para x86 en .NET 4.0 y esto parece resolver el problema. Aunque aún no he ejecutado runtests.bat.

También debe enviar un problema en Connect si aún no se ha enviado uno y vincularlo desde su pregunta.