Definitivamente argumentaría que hay una falla en el diseño si sientes la necesidad de lanzar excepciones desde un establecedor de propiedades o un captador.
Una propiedad es una abstracción que representa algo que es solo un valor . Y debería poder establecer un valor sin temer que hacerlo podría generar una excepción. *
Si establecer los resultados de la propiedad en un efecto secundario, eso debería implementarse como un método. Y si no produce ningún efecto secundario, no se debe lanzar ninguna excepción.
Un ejemplo ya mencionado en una respuesta diferente es Stream.Position
propiedad. Esto produce efectos secundarios, y puede lanzar excepciones. Pero este establecedor de propiedades es básicamente un envoltorio alrededor de Stream.Seek
a los que podrías llamar en su lugar.
Personalmente, creo que la posición no debería haber sido una propiedad de escritura.
Otro ejemplo en el que podría verse tentado a lanzar una excepción desde un establecedor de propiedades es la validación de datos:
public class User {
public string Email {
get { return _email; }
set {
if (!IsValidEmail(value)) throw InvalidEmailException(value);
_email = value;
}
}
Pero hay una mejor solución a este problema. Introduzca un tipo que represente una dirección de correo electrónico válida:
public class Email {
public Email(string value) {
if (!IsValidEmail(value)) throw new InvalidEmailException(value);
...
}
...
}
public class User {
public Email Email { get; set; }
}
La clase Email
garantiza que no puede contener un valor que no sea una dirección de correo electrónico válida, y las clases que necesitan almacenar correos electrónicos no tienen la obligación de validarlos.
Esto también conduce a una mayor cohesión (un indicador del buen diseño del software): el conocimiento sobre qué es una dirección de correo electrónico y cómo se valida, solo existe en la clase Email
, que tiene solo esa preocupación.
* ObjectDisposedException es la única excepción válida (no se pretende hacer un juego de palabras) que se pueda imaginar en este momento.