Sosterrei sicuramente che c'è un difetto nel design se senti la necessità di lanciare eccezioni da un setter o da un getter di proprietà.
Una proprietà è un'astrazione che rappresenta qualcosa che è solo un valore . E dovresti essere in grado di impostare un valore senza temere che farlo potrebbe generare un'eccezione. *
Se l'impostazione della proprietà produce un effetto collaterale, ciò dovrebbe invece essere implementato come metodo. E se non produce effetti collaterali, non deve essere lanciata alcuna eccezione.
Un esempio già menzionato in una risposta diversa è Stream.Position
proprietà. Ciò produce effetti collaterali e può generare eccezioni. Ma questo setter di proprietà è fondamentalmente solo un involucro attorno a Stream.Seek
che potresti chiamare invece.
Personalmente, credo che la posizione non avrebbe dovuto essere una proprietà scrivibile.
Un altro esempio in cui potresti essere tentato di lanciare un'eccezione da un setter di proprietà è la convalida dei dati:
public class User {
public string Email {
get { return _email; }
set {
if (!IsValidEmail(value)) throw InvalidEmailException(value);
_email = value;
}
}
Ma c'è una soluzione migliore a questo problema. Introduci un tipo che rappresenta un indirizzo email valido:
public class Email {
public Email(string value) {
if (!IsValidEmail(value)) throw new InvalidEmailException(value);
...
}
...
}
public class User {
public Email Email { get; set; }
}
La classe Email
garantisce che non possa contenere un valore che non è un indirizzo email valido e le classi che devono memorizzare le e-mail sono sollevate dal dovere di convalidarle.
Ciò porta anche a una maggiore coesione (un indicatore di buona progettazione del software): la conoscenza di cosa sia un indirizzo di posta elettronica e di come viene convalidato esiste solo nella classe Email
, che ha solo questo problema.
* ObjectDisposedException è l'unica eccezione valida (nessun gioco di parole) a cui riesco a pensare al momento.