son - propiedades de las excepciones en c#
¿Qué tipo de excepción usar cuando una propiedad no puede ser nula? (9)
En mi aplicación, necesito lanzar una excepción si una propiedad de una clase específica es nula o está vacía (en caso de que sea una cadena). No estoy seguro de cuál es la mejor excepción para usar en este caso. No me gustaría crear una nueva excepción y no estoy seguro si ArgumentNullException es apropiado en este caso.
¿Debo crear una nueva excepción o hay una excepción que puedo usar?
No me importa lanzar una ApplicationException.
¿El constructor lo establece en un valor no nulo? Si es así, simplemente lanzaría ArgumentNullException
del setter.
Bueno, no es un argumento, si estás haciendo referencia a una propiedad de una clase. Por lo tanto, no debería usar ArgumentException o ArgumentNullException.
NullReferenceException sucedería si solo dejas las cosas en paz, así que supongo que eso no es lo que estás buscando.
Por lo tanto, usar ApplicationExeption o InvalidOperationException sería probablemente su mejor opción, asegurándose de dar una cadena significativa para describir el error.
Es bastante apropiado lanzar ArgumentNullException si alguien intenta asignar null.
Una propiedad nunca debe lanzar en una operación de lectura.
Existe un precedente para extender la interpretación de ArgumentNullException al significado "argumento de cadena es nulo o vacío": System.Windows.Clipboard.SetText arrojará una ArgumentNullException en este caso.
Así que no vería nada malo con el uso de esto en lugar de la ArgumentException más general en su sistema de propiedad, siempre que lo documente.
Las pautas de MSDN para excepciones estándar establecen:
Use el valor para el nombre del parámetro de valor implícito de los establecedores de propiedades.
El siguiente ejemplo de código muestra una propiedad que arroja una excepción si la persona que llama pasa un argumento nulo.
public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } }
Además, las pautas de MSDN para el diseño de propiedades dicen:
Evite arrojar excepciones de los captadores de propiedades.
Los captadores de propiedades deben ser operaciones simples sin condiciones previas. Si un getter arroja una excepción, considere rediseñar la propiedad para que sea un método. Esta recomendación no se aplica a los indexadores. Los indexadores pueden lanzar excepciones debido a argumentos inválidos.
Es válido y aceptable lanzar excepciones desde un establecimiento de propiedades.
Entonces arroje ArgumentNullException
en setter en null
, y ArgumentException
en la cadena vacía, y no haga nada en el getter. Como el colocador lanza y solo usted tiene acceso al campo de respaldo, es fácil asegurarse de que no contenga un valor no válido. Tener el tiro de getter es inútil. Sin embargo, este podría ser un buen lugar para usar Debug.Assert
.
Si realmente no puede proporcionar un valor predeterminado apropiado, entonces supongo que tiene tres opciones:
Simplemente devuelva lo que haya en la propiedad y documente este comportamiento como parte del contrato de uso. Deja que la persona que llama lidie con eso. También podría exigir un valor válido en el constructor. Sin embargo, esto podría ser completamente inapropiado para su aplicación.
Reemplace la propiedad por métodos: un método setter que arroja cuando pasa un valor no válido, y un método getter que arroja
InvalidOperationException
cuando nunca se le asignó un valor válido a la propiedad.Tire
InvalidOperationException
del getter, ya que podría considerar que ''la propiedad nunca ha sido asignada'' a un estado inválido. Si bien no debería tirar normalmente desde getters, supongo que esta podría ser una buena razón para hacer una excepción.
Si elige las opciones 2 o 3, también debe incluir un método TryGet que devuelva un bool
que indique si la propiedad se ha establecido en un valor válido y, de ser así, devuelve ese valor en un parámetro de out
. De lo contrario, obligará a las personas que llaman a estar preparadas para manejar una InvalidOperationException
, a menos que hayan establecido previamente la propiedad y así sepan que no lanzará. Compare int.Parse
versus int.TryParse
.
Sugeriría usar la opción 2 con el método TryGet. No infringe ninguna de las pautas e impone requisitos mínimos sobre el código de llamada.
Sobre las otras sugerencias
ApplicationException
es demasiado general. ArgumentException
es un poco demasiado general para null
, pero bien de lo contrario. MSDN Doc nuevamente :
Lanza la excepción más específica (la más derivada) que sea apropiada. Por ejemplo, si un método recibe un argumento nulo (Nothing en Visual Basic), debería lanzar System.ArgumentNullException en lugar de su tipo base System.ArgumentException.
De hecho, no debería usar ApplicationException
en absoluto ( documentos ):
Obtenga derivaciones personalizadas de la clase T: System.Exception en lugar de la clase T: System.ApplicationException.
Originalmente se pensó que las excepciones personalizadas deberían derivar de la clase ApplicationException; sin embargo, esto no se ha encontrado para agregar un valor significativo. Para obtener más información, vea las Mejores prácticas para manejar excepciones.
InvalidOperationException
está destinado a cuando los argumentos a un método o propiedad no son válidos, sino cuando la operación como un todo no es válida ( documentos ). No debe arrojarse desde el colocador:
Lanza una excepción System.InvalidOperationException si está en un estado inapropiado. System.InvalidOperationException debe lanzarse si un conjunto de propiedades o una llamada a un método no son apropiados dado el estado actual del objeto. Por ejemplo, escribir en un System.IO.FileStream que se haya abierto para leer debería arrojar una excepción System.InvalidOperationException.
Por cierto, InvalidOperationException
es para cuando la operación no es válida para el estado actual del objeto. Si la operación siempre es inválida para toda la clase, debe usar NotSupportedException
.
Si el problema es que un miembro de un argumento, y no el argumento en sí mismo, es nulo, entonces creo que la mejor opción es la ArgumentException
más genérica. ArgumentNullException
no funciona aquí porque el argumento en realidad no es nulo. En su lugar, necesita el tipo de excepción más genérico "algo está mal con su argumento".
Un mensaje detallado para el constructor sería muy apropiado aquí
Si no puede ser nulo o está vacío, haga que su configurador no permita valores nulos o vacíos, o genere una ArgumentException si ese es el caso.
Además, requiere que la propiedad se establezca en el constructor.
De esta forma, fuerza un valor válido, en lugar de regresar más tarde y diciendo que no puede determinar el saldo de la cuenta porque la cuenta no está configurada.
Pero, estaría de acuerdo con la respuesta de bduke.
Solo arroje lo que sea mientras el mensaje de error sea útil para un desarrollador. Esta clase de excepción nunca debería ocurrir fuera del desarrollo, de todos modos.
InvalidOperationException
una InvalidOperationException
. MSDN dice que "se lanza cuando una llamada a un método no es válida para el estado actual del objeto".