Pregunta

Estaba participando en la pregunta de desbordamiento de pila ¿Es todo en .NET un objeto? .

Y un póster (en comentarios de respuesta aceptada) parecía pensar que realizar una llamada al método en un tipo de valor resultó en un boxeo. Me señaló a Boxing and Unboxing (Programación C # Guía) que no especifica exactamente el caso de uso que estamos describiendo.

No soy de confiar 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. : D

Para más detalles:

El ejemplo que utilicé fue:

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

El boxeo no ocurre 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, una " constriñe " El comando CIL se ejecuta antes de un callvirt. De acuerdo con la documentación, OpCodes. Campo restringido , esto da como resultado el boxeo :

  

Si thisType es un tipo de valor y   thisType no implementa el método   entonces ptr se desreferencia, se encuadra y   pasó como el puntero 'this' al   instrucción del método callvirt.

¿Fue útil?

Solución

Aquí está el 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.

Otros consejos

En el caso de que haya dado la respuesta es no, como señaló el zócalo.

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

Considere el código:

interface IZot
{
    int F();
}

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

Entonces

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

no da como resultado 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<*><*>)
    L_0000: nop 
    L_0001: ldloca.s CS<*><*>
    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 

@ ggf31316

  

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

He comprobado ToString por ti. Int32 anula ToString, así que hice una estructura que no lo hace. Utilicé .NET Reflector para asegurar que la estructura no estuviera anulando mágicamente ToString () , y no lo fue.

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 (a través de ILDASM ) para el método Main 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 realizan llamadas de boxeo, si marca la documentación sobre un virt restringido + una llamada , encontrará que establece que el boxeo SÍ tiene lugar. oOo

Cita:

  

Si thisType es un tipo de valor y   thisType no implementa el método   entonces ptr se desreferencia, se encuadra y   pasó como el puntero 'this' al   instrucción del método callvirt.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top