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.