Mejor práctica: ¿valor de retorno de la función o parámetros de salida de referencia?

StackOverflow https://stackoverflow.com/questions/246814

  •  05-07-2019
  •  | 
  •  

Pregunta

Tengo una función llamada FindSpecificRowValue que toma un datatable y devuelve el número de fila que contiene un valor particular. Si no se encuentra ese valor, quiero indicarlo a la función de llamada.

Es el mejor enfoque para:

  1. Escriba una función que devuelva falso si no se encuentra, verdadero si se encuentra, y el número de fila encontrado como un parámetro de referencia / salida, o
  2. Escriba una función que devuelva un int y vuelva a pasar -999 si no se encuentra el valor de la fila, ¿el número de la fila si es?
¿Fue útil?

Solución

Personalmente, tampoco lo haría con ese nombre de método.

En su lugar, haría dos métodos:

TryFindSpecificRow
FindSpecificRow

Esto seguiría el patrón de Int32.Parse / TryParse, y en C # podrían verse así:

public static Boolean TryFindSpecificRow(DataTable table, out Int32 rowNumber)
{
    if (row-can-be-found)
    {
        rowNumber = index-of-row-that-was-found;
        return true;
    }
    else
    {
        rowNumber = 0; // this value will not be used anyway
        return false;
    }
}

public static Int32 FindSpecificRow(DataTable table)
{
    Int32 rowNumber;


    if (TryFindSpecificRow(table, out rowNumber))
        return rowNumber;
    else
        throw new RowNotFoundException(String.Format("Row {0} was not found", rowNumber));
}

Editar: Se modificó para ser más apropiado para la pregunta.

Otros consejos

las funciones que fallan deberían lanzar excepciones.

Si la falla es parte del flujo esperado, entonces el retorno de un valor fuera de banda es correcto, excepto cuando no se puede determinar previamente cuál sería un valor fuera de banda, en cuyo caso tiene que lanzar una excepción.

Si tuviera que elegir entre sus opciones, elegiría la opción 2, pero utilizaría una constante en lugar de -999 ...

También puede definir el valor de retorno como Nullable y no devolver nada si no se encuentra nada.

Elegiría la opción 2. Aunque creo que solo usaría -1 no -999.

Richard Harrison tiene razón en que una constante nombrada es mejor que una simple -1 o -999.

Iría con 2, o alguna otra variación donde el valor de retorno indica si se encontró el valor.

Parece que el valor de la fila a la que la función devuelve (o proporciona una referencia a) ya indica si se encontró el valor. Si no se encontró un valor, parece que no tiene sentido proporcionar un número de fila que no contenga el valor, por lo que el valor de retorno debe ser -1, o Nulo, o cualquier otro valor que sea adecuado para el idioma en particular. De lo contrario, el hecho de que se haya devuelto un número de fila indica que se encontró el valor.

Por lo tanto, no parece ser necesario un valor de retorno separado para indicar si se encontró el valor. Sin embargo, el tipo 1 podría ser apropiado si se ajusta a los modismos del idioma en particular, y la forma en que se realizan las llamadas de función en él.

Vaya con 2) pero devuelva -1 (o una referencia nula si devuelve una referencia a la fila), ese idioma se usa extensivamente (incluso por .nets indexOf (elemento)), es lo que probablemente haría .

BTW -1 es más aceptable y se usa ampliamente " número mágico " que -999, esa es la única razón por la que es " correcta " (citas utilizadas allí por una razón).

Sin embargo, mucho de esto tiene que ver con lo que esperas. ¿El artículo siempre debería estar allí, pero simplemente no sabes dónde? En ese caso, devuelva el índice normalmente y lance un error / excepción si no está allí.

En este caso, es posible que el elemento no esté allí, y esa es una condición aceptable. Es una trampa de error para los valores no seleccionados en un GridView que se enlaza a un datatable.

Otras pocas posibilidades aún no mencionadas:

// Method 1: Supports covariance; can return default<T> on failure.
T TryGetThing(ref bool success); 

// Method 2: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in in case of failure.
T TryGetThing(T DefaultValue);

// Method 3: Does not support covariance, but may allow cleaner code in some cases
// where calling code would use some particular value in case of failure, but should
// not take the time to compute that value except when necessary.
T TryGetThing(Func<T> AlternateGetMethod);

// Method 4: Does support covariance; ErrorMethod can throw if that's what should
// happen, or it can set some flag which is visible to the caller in some other way.
T TryGetThing(Action ErrorMethod);

El primer enfoque es el método inverso al que Microsoft desarrolló en los días previos a la existencia de soporte para interfaces covariantes. El último es, en cierto modo, el más versátil, pero es probable que requiera la creación de un par de nuevas instancias de objetos GC (por ejemplo, un cierre y un delegado) cada vez que se use.

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