2011-11-21 8 views
11

Recientemente realicé algunas mediciones aproximadas del rendimiento en List<> frente a [] para una serie de pequeñas estructuras. System.Array parecía ganar indiscutiblemente, así que fui con eso.¿System.Array realiza boxeo en tipos de valor o no?

Me acabo de dar cuenta de que System.Array contiene tipos de objetos, por lo que seguramente llenarlo de estructuras provocaría el encajamiento.

Sin embargo, the MSDN entry for System.Array estados:

En la versión de .NET Framework 2.0, la clase Array implementa los System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, y System.Collections.Generic.IEnumerable<T> interfaces genéricas. Las implementaciones se proporcionan a las matrices en tiempo de ejecución y, por lo tanto, son no visibles para las herramientas de creación de documentación. Como resultado, las interfaces genéricas no aparecen en la sintaxis de declaración para la clase Array , y no hay temas de referencia para miembros de la interfaz a los que se pueda acceder al fundir una matriz en el tipo de interfaz genérica (implementaciones de interfaz explícita) .

¿Esto significa que el boxeo no se produce después de todo? (Y explicaría los resultados de mi rendimiento)

+0

Para explicar sus resultados de rendimiento probablemente deberíamos ver el código que usó para medir el rendimiento. – Snowbear

Respuesta

12

No usar una matriz no aparece si usa la notación del indexador. p.

new int[2]; 
x=[1]=3; 

compila en el siguiente IL (tenga en cuenta los números de línea son irrelevantes, ya que vienen de algún otro fragmento de código)

IL_0011: ldc.i4.2 
IL_0012: newarr System.Int32 
IL_0017: stfld Int32[] x 
IL_001c: ldarg.0 
IL_001d: ldfld Int32[] x 
IL_0022: ldc.i4.1 
IL_0023: ldc.i4.3 
IL_0024: stelem.i4 

Para los idiomas que no pueden usar el indexador (y realmente no lo saber si existen o no) Se crean otros 2 métodos en el momento de la compilación para Arrays.

Se crea estos métodos públicos ::

public int Get(int index) 
public void Set(int index,int value) 

Esos métodos no sea caja y normalmente no son accesibles a través de C#. (No me preguntes por qué son métodos públicos). Puede ejecutarlos usando IL o creando delegados para ellos. Son más lentos ya que se ven obligados a hacer un callvirt para invocar estos métodos.

La familia stelem. * Y ldelem. * Se utiliza para manejar el almacenamiento en un tipo de matriz fuertemente tipada. Cuando se usan genéricos, generalmente los siguientes prefijos se adjuntan constrained o readonly cuando se usa un T[]. stelem.* tipo, por lo general, no verifica el tipo. P.ej. usar stelem.i4 es más rápido que usar stelem.any Int32, a menos que lo prefija con readonly, porque de lo contrario, fuerza una verificación de tipo.

Ahora la comprobación de tipo es COMPLETAMENTE inútil en las matrices de tipo value, ¡no son covariantes!

Dado que el tiempo de ejecución genera una matriz unidimensional que comienza en cero (ya sea llamado tipo SZ_array o vector), se conocen de forma nativa.

Hay una familia de códigos op il para ellos: newarr, stelem.*, ldelem.*, etc. ldlen

El tipo List<T> utiliza un T[] por su almacén de respaldo en la implementación de Microsoft del BCL. List<T> no encajona. Independientemente de usar list o array, está almacenando cosas en una matriz.

+1

Aquí hay un enlace suplementario a otra respuesta con respecto a la asignación de pila/montón de matrices y sus valores contenidos: http://stackoverflow.com/questions/1113819/arrays-heap-and-stack-and-value-types/1114152#1114152 – BoltClock

+1

Como las matrices son tipos de referencia, las int. Sin caja también se almacenan en el montón administrado; no hay nada de qué ocuparse. – Alex

Cuestiones relacionadas