valor tipo sharp referencia por example ejemplo dato conversion and .net boxing value-type

sharp - ¿Llamar a un método en un tipo de valor resulta en un boxeo en.NET?



ejemplo de tipo de dato por referencia (4)

Solo estaba participando en la pregunta de Stack Overflow. ¿Todo en .NET es un objeto? .

Y un póster (en comentarios de respuesta aceptada) pareció pensar que realizar una llamada a un método en un tipo de valor dio como resultado el boxeo. Me señaló Boxeo y Unboxing (Guía de programación C #) que no especifica exactamente el caso de uso que estamos describiendo.

No soy de los que confían en una sola fuente, así que solo quería obtener más comentarios sobre la pregunta. Mi intuición es que no hay boxeo, pero mi intuición apesta. :RE

Para elaborar más:

El ejemplo que utilicé fue:

int x = 5; string s = x.ToString(); // Boxing??

El boxeo no se produce si la estructura en cuestión anula el método heredado del objeto, como lo indica la respuesta aceptada aquí.

Sin embargo, si la estructura no anula el método, se ejecuta un comando CIL de "restricción" antes de una llamada de llamada. De acuerdo con la documentación, OpCodes.Constrained Field , esto da como resultado el boxeo :

Si thisType es un tipo de valor y thisType no implementa el método, ptr se desreferencia, encajona y pasa como el puntero ''this'' a la instrucción de método callvirt.


Aquí está la IL para su código:

L_0001: ldc.i4.5 // get a 5 on the stack L_0002: stloc.0 // store into x L_0003: ldloca.s x // get the address of x on the stack L_0005: call instance string [mscorlib]System.Int32::ToString() // ToString L_000a: stloc.1 // store in s

Entonces la respuesta en este caso es no.


En el caso que usted haya dado la respuesta es no, como señaló el pedestal.

Sin embargo, lo hará si llama a un método a través de un puntero de interfaz.

Considera el código:

interface IZot { int F(); } struct Zot : IZot { public int F() { return 123; } }

Entonces

Zot z = new Zot(); z.F();

No resulta en el boxeo:

.locals init ( [0] valuetype ConsoleApplication1.Zot z) L_0000: nop L_0001: ldloca.s z L_0003: initobj ConsoleApplication1.Zot L_0009: ldloca.s z L_000b: call instance int32 ConsoleApplication1.Zot::F() L_0010: pop L_0011: ret

Sin embargo, esto hace:

IZot z = new Zot(); z.F(); .locals init ( [0] class ConsoleApplication1.IZot z, [1] valuetype ConsoleApplication1.Zot CS$0$0000) L_0000: nop L_0001: ldloca.s CS$0$0000 L_0003: initobj ConsoleApplication1.Zot L_0009: ldloc.1 L_000a: box ConsoleApplication1.Zot L_000f: stloc.0 L_0010: ldloc.0 L_0011: callvirt instance int32 ConsoleApplication1.IZot::F() L_0016: pop


Creo que llamar a ToString, Equals y Gethashcode resulta en un boxeo si la estructura no anula los métodos.


@ ggf31316

"Creo que llamar a ToString, Equals y Gethashcode resulta en un boxeo si la estructura no anula los métodos".

He comprobado ToString por ti. Int32 sobrescribe ToString, por lo que hice una estructura que no lo hace. Usé .NET Reflector para asegurarme de que la estructura no estaba anulando mágicamente a ToString (), y no era así.

Entonces el código era así:

using System; namespace ConsoleApplication29 { class Program { static void Main(string[] args) { MyStruct ms = new MyStruct(5); string s = ms.ToString(); Console.WriteLine(s); } } struct MyStruct { private int m_SomeInt; public MyStruct(int someInt) { m_SomeInt = someInt; } public int SomeInt { get { return m_SomeInt; } } } }

Y el MSIL (vía ILDASM ) para el método Principal es este:

IL_0000: ldloca.s ms IL_0002: ldc.i4.5 IL_0003: call instance void ConsoleApplication29.MyStruct::.ctor(int32) IL_0008: ldloca.s ms IL_000a: constrained. ConsoleApplication29.MyStruct IL_0010: callvirt instance string [mscorlib]System.Object::ToString() IL_0015: stloc.1 IL_0016: ldloc.1 IL_0017: call void [mscorlib]System.Console::WriteLine(string) IL_001c: ret

Ahora, a pesar de que no se está llevando a cabo una llamada de boxeo, si revisa la documentación sobre una llamada restringida + a de una llamada , encontrará que establece que el boxeo SÍ se lleva a cabo. oOo

Citar:

Si thisType es un tipo de valor y thisType no implementa el método, ptr se desreferencia, encajona y pasa como el puntero ''this'' a la instrucción de método callvirt.