c# - propiedades - tipos de excepciones programacion
¿Qué excepciones deberían arrojarse para los parámetros no válidos o inesperados en.NET? (7)
¿Qué tipos de excepciones se deben arrojar para los parámetros no válidos o inesperados en .NET? ¿Cuándo elegiría uno en lugar de otro?
Seguir:
¿Qué excepción usarías si tienes una función que espera un entero correspondiente a un mes y pasaste el ''42''? ¿Caería esto en la categoría "fuera de rango" aunque no sea una colección?
Dependiendo del valor real y qué excepción se ajusta mejor:
ArgumentException
(algo está mal con el valor)ArgumentNullException
(el argumento es nulo mientras esto no está permitido)ArgumentOutOfRangeException
(el argumento tiene un valor fuera del rango válido)
Si esto no es lo suficientemente preciso, solo obtenga su propia clase de excepción de ArgumentException
.
La respuesta de Yoooder me iluminó. Una entrada no es válida si no es válida en cualquier momento, mientras que una entrada es inesperada si no es válida para el estado actual del sistema. Entonces, en el caso posterior, una InvalidOperationException
es una elección razonable.
Existe una ArgumentException estándar que puede usar, o puede crear una subclase y hacer la suya propia. Hay varias clases específicas de ArgumentException:
http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx
Cualquiera que funcione mejor.
Voté por la respuesta de Josh , pero me gustaría agregar una más a la lista:
System.InvalidOperationException debe lanzarse si el argumento es válido, pero el objeto está en un estado donde el argumento no se debe usar.
Actualización tomada desde MSDN:
InvalidOperationException se usa en los casos en que la falla en invocar un método es causada por razones que no son válidas.
Supongamos que su objeto tiene un método PerformAction (acción enmSomeAction), las enmSomeActions válidas son Abrir y Cerrar. Si llama a PerformAction (enmSomeAction.Open) dos veces seguidas, la segunda llamada arrojará la InvalidOperationException (ya que el algoritmo era válido, pero no para el estado actual del control)
Como ya está haciendo lo correcto al programar a la defensiva, tengo otra excepción que mencionar es ObjectDisposedException. Si su objeto implementa IDisposable, siempre debe tener una variable de clase que rastree el estado dispuesto; si su objeto ha sido eliminado y se le llama a un método, debe elevar ObjectDisposedException:
public void SomeMethod()
{
If (m_Disposed) {
throw new ObjectDisposedException("Object has been disposed")
}
// ... Normal execution code
}
Actualización: para responder a su seguimiento: se trata de una situación un poco ambigua, y se complica un poco más con un tipo de datos genérico (no en el sentido Genérico .NET) que se utiliza para representar un conjunto específico de datos; una enumeración u otro objeto fuertemente tipificado sería un ajuste más ideal, pero no siempre tenemos ese control.
Me inclinaría personalmente hacia ArgumentOutOfRangeException y proporcionaría un mensaje que indica que los valores válidos son 1-12. Mi razonamiento es que cuando hablamos de meses, suponiendo que todas las representaciones de meses enteros son válidas, entonces está esperando un valor en el rango de 1-12. Si solo ciertos meses (como los meses que tenían 31 días) fueran válidos, entonces no se trataría de un Rango per se y arrojaría una ArgumentException genérica que indicara los valores válidos, y también los documentaría en los comentarios del método.
- System.ArgumentException
- System.ArgumentNullException
- System.ArgumentOutOfRangeException
ArgumentException se lanza cuando se invoca un método y al menos uno de los argumentos pasados no cumple con la especificación del parámetro del método llamado. Todas las instancias de ArgumentException deben contener un mensaje de error significativo que describa el argumento no válido, así como el rango esperado de valores para el argumento.
También existen algunas subclases para tipos específicos de invalidez. El enlace contiene resúmenes de los subtipos y cuándo deberían aplicarse.
Respuesta corta:
Ninguno
Respuesta más larga:
el uso de Argument * Exception (excepto en una biblioteca que es un producto en su estado, como la biblioteca de componentes) es un olor. Las excepciones son manejar una situación excepcional, no errores, y no los déficits del usuario (es decir, consumidor API).
La respuesta más larga:
Lanzar excepciones para argumentos inválidos es grosero, a menos que escriba una biblioteca.
Prefiero usar aserciones, por dos (o más) razones:
- Las aserciones no necesitan ser probadas, mientras que las aserciones de throw sí lo hacen, y la prueba contra ArgumentNullException parece ridícula (pruébelo).
- Las aserciones comunican mejor el uso previsto de la unidad, y está más cerca de ser una documentación ejecutable que una especificación de comportamiento de clase.
- Puede cambiar el comportamiento de la violación de afirmación. Por ejemplo, en la compilación de depuración, un cuadro de mensaje está bien, para que su control de calidad lo golpee de inmediato (también obtiene su IDE rompiendo la línea donde sucede), mientras que en la prueba de unidad puede indicar fallas de afirmación como una falla de prueba .
Aquí se muestra cómo se maneja la excepción nula (siendo sarcástico, obviamente):
try {
library.Method(null);
}
catch (ArgumentNullException e) {
// retry with real argument this time
library.Method(realArgument);
}
Las excepciones se usarán cuando la situación sea esperada pero excepcional (ocurren cosas que están fuera del control del consumidor, como una falla de IO). Argumento * La excepción es una indicación de un error y será (mi opinión) manejada con pruebas y asistida con Debug.Assert
Por cierto: en este caso particular, podría haber usado el tipo de mes, en lugar de int. C # se queda corto cuando se trata de tipo de seguridad (Aspect # rulez!) Pero a veces puede evitar (o atrapar en tiempo de compilación) todos esos errores.
Y sí, MicroSoft está equivocado al respecto.
Me gusta usar: ArgumentException
, ArgumentNullException
y ArgumentOutOfRangeException
.
-
ArgumentException
: algo está mal con el argumento. -
ArgumentNullException
- El argumento es nulo. -
ArgumentOutOfRangeException
: no utilizo mucho este, pero un uso común es indexar en una colección y dar un índice que es demasiado grande.
También hay otras opciones que no se enfocan tanto en el argumento en sí mismo, sino que juzgan la llamada como un todo:
-
InvalidOperationException
: el argumento puede estar bien, pero no en el estado actual del objeto. El crédito va a STW (anteriormente Yoooder). Vota su respuesta también. -
NotSupportedException
: los argumentos pasados son válidos, pero simplemente no son compatibles con esta implementación. Imagine un cliente FTP y pasa un comando en el que el cliente no es compatible.
El truco es lanzar la excepción que mejor exprese por qué el método no se puede llamar como es. Idealmente, la excepción debe detallarse sobre qué salió mal, por qué está mal y cómo solucionarlo.
Me encanta cuando los mensajes de error apuntan a ayuda, documentación u otros recursos. Por ejemplo, Microsoft dio un buen primer paso con sus artículos de KB, por ejemplo, "¿Por qué recibo un mensaje de error de" Operación cancelada "cuando visito una página web en Internet Explorer?" . Cuando encuentra el error, lo señalan al artículo de KB en el mensaje de error. Lo que no hacen bien es que no te dicen, por qué específicamente falló.
Gracias a STW (ex Yoooder) nuevamente por los comentarios.
En respuesta a su seguimiento, arrojaría una ArgumentOutOfRangeException
. Mire lo que dice MSDN sobre esta excepción:
ArgumentOutOfRangeException
se inicia cuando se invoca un método y al menos uno de los argumentos pasados al método no es referencia nula (Nothing
en Visual Basic) y no contiene un valor válido.
Entonces, en este caso, está pasando un valor, pero ese no es un valor válido, ya que su rango es 1-12. Sin embargo, la forma en que lo documenta deja en claro qué arroja su API. Porque aunque podría decir ArgumentOutOfRangeException
, otro desarrollador podría decir ArgumentException
. Hazlo fácil y documenta el comportamiento.