Pregunta

No entiendo cuando un parámetro de salida se debe utilizar, personalmente me envuelvo el resultado en un nuevo tipo si necesito devolver más de un tipo, me parece que sea mucho más fácil de trabajar que fuera.

He visto método como este,

   public void Do(int arg1, int arg2, out int result)

¿existen casos en los que realmente tiene sentido?

¿qué tal TryParse, por qué no devolver un tipo ParseResult? o en el marco más reciente devolver un tipo nulables?

¿Fue útil?

Solución

Out es buena cuando se tiene una función TryNNN y está claro que el parámetro de salida será siempre actualizada incluso si la función no tiene éxito. Esto permite que se basan en el hecho de que la variable local se declara se fijará en lugar de tener que colocar los cheques adelante en el código contra nula. (Un comentario más abajo indica que el parámetro puede ser ajustado a null, por lo que es posible que desee comprobar la documentación de la función que está llamando para estar seguro de si este es el caso o no.) Esto hace que el código un poco más claro y más fácil leer. Otro caso es cuando se necesita para devolver algunos datos y un estado de la condición del método como:

public bool DoSomething(int arg1, out string result);

En este caso, el retorno puede indicar si la función tuvo éxito y el resultado se almacena en el parámetro de salida. Es cierto que este ejemplo es artificial porque se puede diseñar de manera que la función simplemente devuelve un string, pero se entiende la idea.

Una desventaja es que usted tiene que declarar una variable local para usarlos:

string result;
if (DoSomething(5, out result))
    UpdateWithResult(result);

En lugar de:

UpdateWithResult(DoSomething(5));

Sin embargo, que ni siquiera puede ser una desventaja, que depende del diseño que vamos a dar. En el caso de DateTime, ambos medios (analizar y TryParse) se proporcionan.

Otros consejos

Así como con la mayoría de las cosas depende. Veamos las opciones

  • que podría volver lo que desea que sea el valor de retorno de la función
  • Si desea devolver varios valores o la función ya tiene un valor de retorno, puede utilizar fuera params o crear un nuevo tipo de compuesto que expone todos estos valores como propiedades

En el caso de TryParse, utilizando un parámetro a cabo es eficiente - usted no tiene que crear un nuevo tipo que sería 16B de la cabeza (32b de máquinas) o incurrir en el coste Potencia de tenerlos basura recogida posterior a la llamada. TryParse podría ser llamado desde el interior de un bucle, por ejemplo - tan fuera params regla aquí
. Para las funciones que no serían llamados dentro de un bucle (rendimiento es decir, no es una preocupación importante), devolviendo un objeto compuesto solo podría ser 'limpia' (subjetiva al espectador). Ahora, con los tipos anónimos y tipado dinámico, que podría llegar a ser aún más fácil.

Nota:

  1. params out haber algunas reglas que deben ser seguidas es decir, el compilador se asegurará de que la función hace inicializar el valor antes de que salga. Así TryParse tiene que establecer el parámetro a un valor incluso si la operación de análisis no
  2. El patrón TryXXX es un buen ejemplo de cuándo utilizar a cabo params - Int32.TryParse se introdujo coz personas se quejaron de la exitosa Potencia de la captura de excepciones de análisis para saber si falló. También lo más probable es que haría en el caso de análisis tenido éxito, es obtener el valor analizado - utilizando un parámetro a cabo significa que usted no tiene que hacer otra llamada al método Parse

Creo cabo es útil para situaciones en las que necesita para volver tanto un valor lógico y un valor, como TryParse, pero sería bueno si el compilador permitiría que algo como esto:

bool isValid = int.TryParse("100", out int result = 0);

En definitiva, un vistazo a los parámetros están destinados a ser utilizados cuando se tiene un método que tiene que devolver más de un valor, en el ejemplo informados:

public void Do(int arg1, int arg2, out int result)

No hace mucho sentido utilizar un parámetro de salida, ya que sólo está devolviendo un valor, y que el método podría utilizarse mejor si se quita el parámetro de salida y poner un valor int retorno:

public int Do(int arg1, int arg2)

Hay algunas cosas buenas sobre parámetros OUT:

  1. Los parámetros de salida se consideran inicialmente sin asignar.
    • Cada parámetro out debe ser definitivamente asignado antes se devuelve el método, el código no se compilará si se olvida de una asignación.

En conclusión, Básicamente intento utilizar a cabo params en mi API privada para evitar la creación de tipos separados para envolver múltiples valores de retorno, y en mi API pública, que sólo los utilizan en los métodos que coinciden con el TryParse patrón.

Los años de retraso con una respuesta, lo sé. a cabo (y así ref) también es muy útil si no desea que su método no instanciar un nuevo objeto para volver. Esto es muy relevante en sistemas de alto rendimiento en las que desee conseguir un rendimiento sub microsegundo para su método. creación de instancias es relativamente caro visto desde una perspectiva de acceso a la memoria.

Creación de un tipo que acaba de regresar a los valores suena poco doloroso para mí :-) En primer lugar voy a tener que crear un tipo para devolver el valor a continuación, en el método de llamada tengo asignar el valor del tipo devuelto a la variable real que lo necesita.

Sin parámetros son simipler a utilizar.

Sí, sí tiene sentido. Tome este por ejemplo.

String strNum = "-1";
Int32 outNum;

if (Int32.TryParse(strNum, out outNum)) {
    // success
}
else {
    // fail
}

¿Qué podría volver si la operación ha fallado en una función normal con un valor de retorno? Que sin duda no podía volver -1 para representar una falla, porque entonces no habría ninguna diferencia entre el valor a prueba de retorno y el valor real que se está analizando, para empezar. Es por esto que devuelven un valor booleano para ver si tenía éxito, y si lo hizo entonces tenemos nuestro valor de "retorno" de manera segura ya asignado.

Se me molesta que no puedo pasar en nulo al parámetro de salida para las funciones TryParse.

Sin embargo, yo prefiero que en algunos casos para devolver un nuevo tipo con dos piezas de datos. Especialmente cuando están sin relación en su mayor parte o de una sola pieza solamente se necesita para una sola operación un momento después. Cuando necesito para guardar el valor resultante de una función TryParse me gusta mucho tener un parámetro de salida en lugar de alguna clase ResultAndValue al azar que tengo que tratar.

Si siempre crea un tipo, entonces se puede terminar con una gran cantidad de desorden en su aplicación.

Como se ha dicho aquí, un caso de uso típico es un método TrySomething en la que desea devolver un bool como un indicador para el éxito y el valor real. También me parece que un poco más limpia en una sentencia if--. las tres opciones más o menos tiene el mismo LOC todos modos

int myoutvalue;
if(int.TryParse("213",out myoutvalue){
    DoSomethingWith(myoutvalue);
}

vs.

ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
    DoSomethingWith(myoutvalue.Value);
}

vs.

int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
    DoSomethingWith(myoutvalue.Value);
}

En cuanto a la "¿Por qué no devolver un tipo anulable": existe TryParse desde 1.x Marco, mientras que los tipos anulables vinieron con 2,0 (Dado que requieren los genéricos). Entonces, ¿por compatibilidad ruptura innecesariamente o iniciar la introducción de inconsistencias entre TryParse en algunos tipos? Siempre se puede escribir su propio método de extensión para duplicar la funcionalidad ya existente (Ver Eric Lipperts Mensaje sobre un tema no relacionado que incluye un razonamiento detrás de hacer / no hacer cosas)

Otro caso de uso es si tiene que devolver múltiples valores no relacionados, a pesar de que si lo hace que active una alarma que su método es posiblemente haciendo demasiado. Por otro lado, si su método es algo así como una base de datos o en la web costosa llamada de servicio y que desea almacenar en caché el resultado, puede tener sentido para hacer eso. Claro, usted podría crear un tipo, pero de nuevo, eso significa que un tipo más en su aplicación.

Yo uso a cabo parámetros veces para facilitar la lectura, al leer el nombre del método es más importante que cualquiera que sea la salida del método es, en particular para los métodos que ejecutan comandos, además de devolver los resultados.

StatusInfo a, b, c;

Initialize(out a);
Validate(a, out b);
Process(b, out c);

vs.

StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);

Al menos para mí, me puso mucho énfasis en los primeros caracteres de cada línea cuando estoy escaneando. Puedo decir fácilmente lo que está pasando en el primer ejemplo después de reconocer que algunas variables "StatusInfo" se declaran. En el segundo ejemplo, el primero que veo es que un montón de StatusInfo se recupera. Tengo que escanear una segunda vez para ver qué tipo de efectos pueden tener los métodos.

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