2011-01-26 7 views
14

Estoy enterado de que boxing and unboxing are relatively expensive en términos de rendimiento. Lo que me pregunto es:¿Pasar un tipo de valor en un parámetro de "salida" hace que la variable esté encuadrada?

¿Pasar un tipo de valor al método out parámetro causa el boxeo/unboxing de la variable (y por lo tanto un golpe de rendimiento)? ¿Puede el compilador optimizar esto?

int number; 
    bool result = Int32.TryParse(value, out number); 
+0

Optimización prematura de búsqueda. El análisis de un entero (análisis en general) es mucho más costoso que una simple operación de boxeo. – Dykam

+0

@Dykam: cierto. Sin embargo, estoy usando 'TryParse' como ejemplo. –

Respuesta

18

Como otros han señalado, no hay boxeo aquí. Cuando pasa una variable como argumento correspondiente a un parámetro de salida o ref, lo que está haciendo es haciendo un alias a la variable. No está haciendo nada con el valor de la variable. Está haciendo que dos variables representen la misma ubicación de almacenamiento.

El boxeo solo ocurre cuando un valor de un tipo de valor se convierte a un valor de un tipo de referencia, y no hay conversión de ningún tipo en su ejemplo. El tipo de referencia debe ser, por supuesto, System.Object, System.ValueType, System.Enum o cualquier interfaz. Por lo general, es bastante claro; hay una conversión explícita o implícita en el código. Sin embargo, puede haber circunstancias en las que es menos claro. Por ejemplo, cuando se llama a un método virtual no reemplazado del tipo base de una estructura, hay boxeo. (También existen situaciones extrañas en las que ciertos tipos de restricciones de tipo genérico pueden causar un boxeo inesperado, pero generalmente no aparecen en la práctica).

+0

Gracias por la respuesta. ¿Todavía hay un golpe de rendimiento involucrado? ¿Cómo se compara con los hits del boxeo/unboxing, pasar un tipo de referencia o pasar un tipo de valor? –

+6

@Justin: El mejor consejo para cualquier pregunta de rendimiento: ** pruébalo y lo sabrás **. Lo que probablemente encontrará es que pasar una variable por referencia es el mismo costo que pasar una referencia a una instancia de un tipo de referencia por referencia, que es el mismo costo que pasar un tipo de valor de tamaño IntPtr. Tenga en cuenta que el paso de parámetros del tamaño de un puntero puede ser muy optimizado por el jitter si hay registros disponibles. –

5

No, no hay boxeo (requerido/involucrado).

Cuando hace una variable Box, los cambios a la instancia en caja no afectan al original. Pero eso es exactamente lo que se supone que debe hacer out.

El compilador 'de alguna manera' construye una referencia a la variable original.

+0

Gracias por la respuesta. ¿Sabes si todavía hay un golpe de rendimiento involucrado? ¿Cómo se compara con el golpe del boxeo/unboxing, o pasar parámetros ordinarios? –

+1

@Justin, la sobrecarga dependería de las circunstancias (campo o var local) pero para un 'out' local probablemente sea el más rápido. Tendrá que medir para _su_ situación. Pero es una micro optimización en el mejor de los casos y no hay alternativas reales. –

1

No hay boxeo; lo que hace el parámetro out es que se debe asignar ese número dentro del método TryParse. Independientemente de esto, todavía se trata como int, no como object.

6

Ningún compilador de boxeo utiliza la instrucción ldloca.s que envía una referencia a la variable local en la pila (http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes. ldloca_s (VS.71) .aspx)

.method private hidebysig static void Func() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] int32 num, 
     [1] bool flag) 
    L_0000: nop 
    L_0001: ldstr "5" 
    L_0006: ldloca.s num 
    L_0008: call bool [mscorlib]System.Int32::TryParse(string, int32&) 
    L_000d: stloc.1 
    L_000e: ret 
} 
Cuestiones relacionadas