the - C#rendimiento del parámetro de salida
the out parameter must be assigned to before control leaves the current method (6)
Dudo que encuentre una penalización de rendimiento significativa al usar un parámetro de out
. Tienes que devolverle la información a la persona que llama de una forma u otra; la out
es solo una manera diferente de hacerlo. Puede encontrar una penalización si usa el parámetro out extensivamente dentro del método, ya que puede significar un nivel extra de redirección para cada acceso. Sin embargo, no esperaría que sea significativo. Como es normal, escriba el código más legible y pruebe si el rendimiento ya es lo suficientemente bueno antes de tratar de optimizarlo aún más.
EDITAR: El resto de esto es un lado, efectivamente. Solo es realmente relevante para tipos de gran valor, que por lo general deberían evitarse :)
No estoy de acuerdo con la afirmación de Konrad acerca de que "los valores de devolución para todos los tipos> de 32 bits se manejan de forma similar o idéntica a los argumentos de salida en el nivel de la máquina de todos modos". Aquí hay una pequeña aplicación de prueba:
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
struct BigStruct
{
public Guid guid1, guid2, guid3, guid4;
public decimal dec1, dec2, dec3, dec4;
}
class Test
{
const int Iterations = 100000000;
static void Main()
{
decimal total = 0m;
// JIT first
ReturnValue();
BigStruct tmp;
OutParameter(out tmp);
Stopwatch sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs = ReturnValue();
total += bs.dec1;
}
sw.Stop();
Console.WriteLine("Using return value: {0}",
sw.ElapsedMilliseconds);
sw = Stopwatch.StartNew();
for (int i=0; i < Iterations; i++)
{
BigStruct bs;
OutParameter(out bs);
total += bs.dec1;
}
Console.WriteLine("Using out parameter: {0}",
sw.ElapsedMilliseconds);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static BigStruct ReturnValue()
{
return new BigStruct();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void OutParameter(out BigStruct x)
{
x = new BigStruct();
}
}
Resultados:
Using return value: 11316
Using out parameter: 7461
Básicamente, al usar un parámetro de salida, estamos escribiendo los datos directamente en el destino final, en lugar de escribirlos en el marco de pila del método pequeño y luego copiarlo nuevamente en el marco de pila del método Principal.
Sin embargo, no dude en criticar la aplicación de referencia: ¡es posible que me haya perdido algo!
¿Los parámetros de salida en C # tienen alguna implicación en el rendimiento que deba conocer? (Como excepciones)
Quiero decir, ¿es una buena idea tener un método con un parámetro de out
en un bucle que se ejecute un par de millones de veces por segundo?
Sé que es feo, pero lo estoy usando de la misma manera que Int32.TryParse
está usando - devolviendo un bool
para decir si alguna validación fue exitosa y teniendo un parámetro de out
que contenga algunos datos adicionales si fue exitoso.
La razón principal para evitar los parámetros es la legibilidad del código, en lugar del rendimiento.
Para los tipos de valor no hay diferencia real de todos modos (siempre copian) y para los tipos de referencia es básicamente lo mismo que pasar por ref.
Nueve de cada diez veces es mejor que crees tu propia clase de grabación estúpida, en lugar de usar un parámetro de salida; es más fácil de leer y comprender cuando vuelves al código más tarde.
Los parámetros de salida se pasan por ref. Entonces solo un puntero pasó en la pila.
Si su tipo de valor es grande, hay menos copia, pero luego debe desreferenciar el puntero en cada uso de variable.
No hay implicaciones de rendimiento. out
es básicamente lo mismo que cualquier argumento pasado, desde un punto de vista técnico. Si bien puede sonar plausible que se copien enormes cantidades de datos (por ejemplo, para estructuras grandes), esto es realmente lo mismo que para los valores de retorno.
De hecho, los valores de retorno para todos los tipos> 32 bits se manejan de manera similar a out
argumentos de out
en el nivel de la máquina .
Tenga en cuenta que la última declaración no sugiere que se devuelva un valor == parámetro de out
en .NET. El punto de referencia de Jon muestra que obviamente este (y lamentablemente) no es el caso. De hecho, para hacerlo idéntico, la optimización del valor de retorno se utiliza en los compiladores de C ++. Algo similar podría hacerse potencialmente en versiones futuras del JIT para mejorar el rendimiento de las estructuras grandes que regresan (sin embargo, dado que las estructuras grandes son bastante raras en .NET, esto podría ser una optimización innecesaria).
Sin embargo , (y con mi conocimiento muy limitado del ensamblaje x86), devolver objetos de llamadas a funciones generalmente implica asignar suficiente espacio en el sitio de llamadas, presionar la dirección en la pila y llenarla copiando el valor de retorno en ella. Esto es básicamente lo mismo que out
, omitiendo una copia temporal innecesaria del valor, ya que se puede acceder directamente a la ubicación de la memoria de destino.
Usar un parámetro de salida no afecta el rendimiento. Un parámetro Out es básicamente un parámetro de referencia, por lo que tanto el que llama como el que llama apuntan a la misma pieza de memoria.
No es un problema de rendimiento, sino algo que surgió antes: no puede usarlos con varianza en C # 4.0 .
Personalmente, tiendo a usar out
parámetros de una cantidad justa en mi código privado (es decir, dentro de una clase, teniendo un método que devuelve múltiples valores sin usar un tipo separado), pero tiendo a evitarlos en la API pública, a excepción del bool Try{Something}(out result)
patrón bool Try{Something}(out result)
.