Una vera risposta alla tua domanda deve occuparsi di altre domande alle quali solo tu puoi rispondere:
- Qual è l'uso previsto della tua classe base?
- Il tuo
base.DoSomething(someProp)
dovrebbe essere chiamato prima?
- In che modo la classe base gestisce il parametro null?
- È nullo un valore valido? In alcuni casi lo è, quindi il lancio di eccezioni sarebbe sbagliato.
Dopo fornirò alcune linee guida che aiuteranno durante il debug:
Non devi sempre generare eccezioni
Fornire valori predefiniti può essere un buon modo per mantenere il sistema stabile, in particolare nei casi in cui il parametro potrebbe essere intenzionalmente nullo. In quei casi potrebbe essere meglio semplicemente tornare immediatamente. Le eccezioni sono costose e sono spesso abusate.
A volte si può fare bene con Debug.Assert()
per rendere dolorosamente ovvio che c'è qualcosa di sbagliato nella build di sviluppo, che dà anche al programmatore la possibilità di entrare nel codice con il debugger con lo stack corrente. Nella build di produzione questi controlli spariscono, il che può accelerare il tempo di esecuzione - basta fare attenzione che le asserzioni non abbiano effetti collaterali a cui si sta dipendendo in fase di esecuzione.
Pubblica l'eccezione appropriata
Quando si verifica un parametro e si trova null, è necessario throw new System.ArgumentNullException(nameof(parameter));
. Questo aiuta a rimuovere accidentalmente NullReferenceException
s dalle cose che hai controllato.
Quando i parametri richiedono più restrizioni del semplice esistente (ovvero devono essere un numero positivo maggiore di 0, ecc.), quindi lanciare l'appropriato ArgumentException
che aiuta l'utente a capire cosa non va.
Fornire il nome del parametro a ArgumentNullException
accelera notevolmente il debug, in particolare quando ci sono più parametri. L'eccezione genera un messaggio di facile lettura che include il nome del parametro che hai fornito e una traccia stack che porta al metodo chiamato. Tutto ciò che puoi fare per ridurre al minimo il tempo in un debugger ti aiuterà a risolvere i problemi più velocemente.
Assicurati che il parametro non sia null prima di accedervi
Ogni programmatore è responsabile di assicurarsi che il parametro sia valido prima di fare qualcosa con esso. Se fai sapere che la tua classe base è destinata ad essere chiamata per prima e gestisce i parametri nulli, ciò non giustifica i programmatori che creano sottoclassi dal controllo di null se stessi se violano tale aspettativa.
Progetta per il debug
Fai tutto il possibile per garantire che il tuo codice sia facile da eseguire il debug e mantenere il più possibile. Il fatto è che la parte più difficile nel correggere bug è trovare dove si trovano in primo luogo. Spesso questo è un compromesso tra lanciare eccezioni e fare il meglio che può quando il parametro fornito è nullo.
Personalmente ritengo che la sottoclasse sia sovrautilizzata e possa portare a casi d'uso imprevedibili perché i client del codice possono avere accesso a determinati stati di classe e fare cose che non sono mai state pensate per iniziare. Se utilizzi la sottoclasse, imposta i punti di estensione abstract
. Se la composizione può ottenere ciò che desideri, potrebbe essere un modello migliore e più prevedibile per estendere le funzionalità di base.
Rendi i punti di estensione abstract
anziché virtual
Si vede questo schema dappertutto nell'API WinForms. Hai il metodo che promette di fare qualcosa, come l'aggiornamento e il ridisegno. La classe base ha un puro metodo abstract
con il prefisso Do
davanti in questo modo:
public abstract class MyBaseClass
{
public void UpdateSomething(ClassA parameter)
{
if (parameter == null) throw new ArgumentNullException(nameof(parameter));
DoUpdateSomething(parameter);
}
protected abstract void DoUpdateSomething(ClassA parameter);
}
Questo approccio ti consente di eseguire tutti i controlli di integrità nel metodo wrapper e di chiamare l'implementazione della sottoclasse solo quando tutto è valido. Questo sarà l'unico modo per garantire che gli opportuni controlli siano fatti nell'ordine giusto e dare agli utenti della tua classe base la certezza che lo stanno usando correttamente.