Actualmente estoy trabajando en un problema que involucra la generación de código System.Reflection.Emit
. Intento averiguar qué CIL emitir en los lugares donde usaría default(SomeType)
en C#.¿Cómo traducir "por defecto (SomeType)" de C# a CIL?
He realizado algunos experimentos básicos de Visual Studio 11 Beta. JustDecompile me muestra el siguiente resultado CIL para default(bool)
, default(string)
y default(int?
:
.locals init (
[0] bool V_0,
[1] string V_1,
[2] valuetype [mscorlib]System.Nullable`1<int32> V_2
)
// bool b = default(bool);
ldc.i4.0
stloc.0
// string s = default(string);
ldnull
stloc.1
// int? ni = default(int?);
ldloca.s V_2
initobj valuetype [mscorlib]System.Nullable`1<int32>
A juzgar por esto, default(T)
parece que se resolvió por el compilador para el CIL más adecuado para los tipos dados.
Fui a ver lo que sucedería en el caso más general, utilizando tres métodos genéricos:
T CreateStructDefault<T>() where T : struct { return default(T); }
T CreateClassDefault<T>() where T : class { return default(T); }
T CreateClassNull<T>() where T : class { return null; }
Los tres métodos producen los mismos CIL método de cuerpo:
.locals init (
[0] !!T V_0,
[1] !!T V_1
)
IL_0000: nop
IL_0001: ldloca.s V_1
IL_0003: initobj !!T
IL_0009: ldloc.1
IL_000a: stloc.0
IL_000b: br.s IL_000d
IL_000d: ldloc.0
IL_000e: ret
Pregunta:
¿Puedo concluir de todo esto que C# 's default(SomeType)
corresponde más estrechamente a CIL & hellip;
initobj
para los tipos no primitivos (exceptostring
?)ldc.iX.0
/ldnull
/etc. para los tipos primitivos (másstring
)?
y por qué CreateClassNull<T>
no sólo se traducen en ldnull
, pero a initobj
en su lugar? Después de todo, se emitió ldnull
para string
(que también es un tipo de referencia).
¿Qué quieres decir con tipos 'primitivos'? Hay tipos de valores y tipos de referencia. Esperaría ldnull con tipos de referencia (incluida la cadena). \ – sehe
Con "tipos primitivos", me refiero a los que son originalmente compatibles con el CTS (?) - 'bool',' byte', 'char',' int ',' float', 'double', etc. Aquellos que, a diferencia del valor definido por el usuario o de los tipos de referencia, no son compuestos y no pueden dividirse en tipos más básicos. – stakx
Observo que debe estar mirando el codegen sin depurar, depurado, dado que el compilador no ha eliminado una rama de la siguiente instrucción. –