A veces termino teniendo que escribir un método o propiedad para una biblioteca de clases para la cual no es excepcional no tener una respuesta real, sino un error. Algo no se puede determinar, no está disponible, no se encuentra, actualmente no es posible o no hay más datos disponibles.
Creo que hay tres soluciones posibles para una situación tan relativamente no excepcional para indicar un error en C # 4:
- devuelve un valor mágico que no tiene otro significado (como
null
y-1
); - lanzar una excepción (por ejemplo,
KeyNotFoundException
); - devuelve
false
y proporciona el valor de retorno real en un parámetroout
, (comoDictionary<,>.TryGetValue
).
Entonces, las preguntas son: ¿en qué situación no excepcional debo lanzar una excepción? Y si no debo lanzar: cuando se está devolviendo un valor mágico preferido arriba implementando un Try*
método con un parámetro out
? (Para mí, el parámetro out
parece sucio, y es más trabajo usarlo correctamente).
Estoy buscando respuestas objetivas, como respuestas que incluyan pautas de diseño (no conozco ninguno sobre los métodos Try*
), facilidad de uso (ya que solicito esto para una biblioteca de clases), coherencia con el BCL y legibilidad .
En la biblioteca de clases base de .NET Framework, se utilizan los tres métodos:
- devuelve un valor mágico que no tiene otro significado:
-
Collection<T>.IndexOf
devuelve -1, -
StreamReader.Read
devuelve -1, -
Math.Sqrt
devuelve NaN, -
Hashtable.Item
devuelve un valor nulo;
-
- lanzar una excepción:
-
Dictionary<,>.Item
lanza la excepción KeyNotFoundException, -
Double.Parse
lanza FormatException; o
-
- devuelve
false
y proporciona el valor de retorno real en un parámetroout
:
Tenga en cuenta que como Hashtable
se creó en el momento en que no había genéricos en C #, utiliza object
y, por lo tanto, puede devolver null
como un valor mágico. Pero con los genéricos, las excepciones se utilizan en Dictionary<,>
, e inicialmente no tenía TryGetValue
. Aparentemente las ideas cambian.
Obviamente, la dualidad Item
- TryGetValue
y Parse
- TryParse
está ahí por una razón, así que asumo que lanzar excepciones para fallas no excepcionales está en C # 4 no hecho . Sin embargo, los métodos Try*
no siempre existieron, incluso cuando existía Dictionary<,>.Item
.