Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

355
Vistas
¿Los genéricos de C# evitan el autoboxeo de estructuras en este caso?

Por lo general, tratar una estructura S como una interfaz activará el I de la estructura, lo que puede tener un impacto en el rendimiento si se hace con frecuencia. Sin embargo, si escribo un método genérico tomando un parámetro de tipo T : I y lo llamo con una S , ¿el compilador omitirá el boxeo, ya que conoce el tipo S y no tiene que usar la interfaz?

Este código muestra mi punto:

 interface I{ void foo(); } struct S : I { public void foo() { /* do something */ } } class Y { void doFoo(I i){ i.foo(); } void doFooGeneric<T>(T t) where T : I { t.foo(); // <--- Will an S be boxed here?? } public static void Main(string[] args){ S x; doFoo(x); // x is boxed doFooGeneric(x); // x is not boxed, at least not here, right? } }

El método doFoo llama a foo() en un objeto de tipo I , por lo que una vez que lo llamemos con una S , esa S quedará encuadrada. El método doFooGeneric hace lo mismo. Sin embargo, una vez que lo llamamos con una S , es posible que no se requiera autoboxing, ya que el tiempo de ejecución sabe cómo llamar a foo() en una S ¿Pero se hará esto? ¿O el tiempo de ejecución encuadrará ciegamente S a I para llamar al método de interfaz?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

void doFooGeneric<T>(T t) where T : I { t.foo(); // <--- Will an S be boxed here?? }

¡Se evitará el boxeo allí!

La estructura tipo S está sellada. Para las versiones de tipo de valor del parámetro de tipo T para su método doFooGeneric anterior, el compilador de C# brinda un código que llama al miembro de estructura relevante directamente, sin recuadro.

que es genial

Consulte la respuesta de Sameer para obtener algunos detalles técnicos.


Bien, se me ocurrió un ejemplo de esto. Estaré interesado en mejores ejemplos si alguien tiene algunos:

 using System; using System.Collections.Generic; namespace AvoidBoxing { static class Program { static void Main() { var myStruct = new List<int> { 10, 20, 30, }.GetEnumerator(); myStruct.MoveNext(); // moves to '10' in list // // UNCOMMENT ONLY *ONE* OF THESE CALLS: // //UseMyStruct(ref myStruct); //UseMyStructAndBox(ref myStruct); Console.WriteLine("After call, current is now: " + myStruct.Current); // 10 or 20? } static void UseMyStruct<T>(ref T myStruct) where T : IEnumerator<int> { myStruct.MoveNext(); } static void UseMyStructAndBox<T>(ref T myStruct) { ((IEnumerator<int>)myStruct).MoveNext(); } } }

Aquí, el tipo de myStruct es un tipo de valor mutable que contiene una referencia a List<> , y también contiene un "contador" que recuerda qué índice en List<> hemos alcanzado hasta ahora.

¡Tuve que usar ref , de lo contrario, el tipo de valor se copiaría por valor cuando se pasara a cualquiera de los métodos!

Cuando elimino el comentario de la llamada a UseMyStruct (solo), este método mueve el "contador" dentro de nuestro tipo de valor una posición por delante. Si hiciera eso en una copia en caja del tipo de valor, no lo veríamos en la instancia original de la estructura.

Para ver cuál es la diferencia con el boxeo, intente llamar a UseMyStructAndBox en su lugar (comente UseMyStruct nuevamente). Crea un cuadro en el molde y MoveNext ocurre en una copia. ¡Así que la salida es diferente!


Para aquellos que no están contentos con (o confundidos por) el ref , simplemente escriba Current desde dentro del método en su lugar. Entonces podemos deshacernos de ref . Ejemplo:

 static void F<T>(T t) where T : IEnumerator<int> { t.MoveNext(); // OK, not boxed Console.WriteLine(t.Current); } static void G<T>(T t) where T : IEnumerator<int> { ((IEnumerator<int>)t).MoveNext(); // We said "Box!", it will box; 'Move' happens to a copy Console.WriteLine(t.Current); }
over 4 years ago · Santiago Trujillo Denunciar

0

Se evitará el boxeo ya que los códigos de operación restringidos entran en juego en el segundo caso.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda