c# validation exception properties

c# - ¿Qué excepción lanzar desde un setter de propiedad?



validation exception (7)

Tengo una propiedad de cadena que tiene un requisito de longitud máxima porque los datos están vinculados a una base de datos. ¿Qué excepción debo lanzar si la persona que llama intenta establecer una cadena que excede esta longitud?

Por ejemplo, este código C #:

public string MyProperty { get { return _MyBackingField; } set { if (value.Length > 100) throw new FooException("MyProperty has a maximum length of 100."); _MyBackingField = value; } }

Consideré ArgumentException , pero simplemente no parece correcto. Técnicamente , es una función - MyProperty_set(string value) - por lo que se puede hacer un caso para ArgumentException , pero no se llama como una función a los ojos del consumidor: está en el lado derecho de un operador de asignación.

Esta pregunta probablemente también podría extenderse para incluir todo tipo de validación de datos realizada en el establecimiento de propiedades, pero estoy particularmente interesado en el caso anterior.


¿Recuerda cuántos problemas en informática se resuelven agregando un nivel extra de indirección?

Un enfoque sería crear un nuevo tipo, FixedLengthString, por ejemplo. Sería casos de ese tipo que validan las longitudes de las cadenas con las que se inicializan, con un operador de conversión para hacer una conversión de tipo desde una cadena simple. Si su creador de propiedades toma un tipo como su argumento, cualquier violación se convertiría en una excepción de conversión de tipo en lugar de una excepción de argumento / propiedad.

En la práctica, rara vez haría esto. Huele un poco a tomar OO demasiado lejos, pero en algunos casos puede ser una técnica útil, así que lo menciono aquí para completar.


Eche un vistazo a través de mscorlib.dll con Reflector, en una situación similar como System.String.StringBuilder.Capacity Microsoft use ArgumentOutOfRangeException () similar a:

public int PropertyA { get { return //etc... } set { if (condition == true) { throw new ArgumentOutOfRangeException("value", "/* etc... */"); } // ... etc } }


Intenta usar las excepciones existentes siempre que sea posible. En este caso, use InvalidOperationException porque el valor entrante está llevando el objeto a un estado incoherente. Se pueden crear excepciones personalizadas cuando se necesita un manejo específico con la excepción personalizada. En este caso, solo lanza una excepción con algo de texto, así que use InvalidOperationException.

Al lanzar InvalidOperationException muestra el valor que se ha pasado a este setter.


No lanzaría una excepción en absoluto. Más bien, permitiría una cadena de cualquier longitud y luego tendré un método "Validate" separado en la clase a la que se llama antes de guardar. Hay una serie de escenarios, especialmente si utiliza enlaces de datos donde arrojar excepciones de los responsables de la creación de la propiedad puede desordenarlo.

El problema con arrojar excepciones de los establecedores de propiedades es que los programadores se olvidan de atraparlos. Depende de cuán limpio usted espera que sean los datos que obtiene. En este caso, esperaría que las longitudes de cadena largas sean comunes, no excepcionales y, como tal, el uso de una excepción sería "control de flujo con excepciones".

Para citar las Pautas de diseño de Microsoft para desarrollar bibliotecas de clase :

No use excepciones para un flujo de control normal, si es posible. Excepto por las fallas del sistema y las operaciones con posibles condiciones de carrera, los diseñadores del marco deben diseñar API para que los usuarios puedan escribir código que no arroje excepciones. Por ejemplo, puede proporcionar una forma de verificar las condiciones previas antes de llamar a un miembro para que los usuarios puedan escribir código que no arroje excepciones.


Para mí, ArgumentException (o un elemento secundario) tiene más sentido, porque el argumento (valor) que proporcionó no es válido, y para esto se creó ArgumentException.


Puede usar InvalidOperationException. Eso es un compromiso. No me molestaría en usar una ArgumentException tampoco.


public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } }

a través de MSDN