2011-01-25 11 views
9

Sto davvero cercando di capire le migliori pratiche per il codice riutilizzabile che è facilmente debug. Mi sono imbattuto in una pratica comune tra sviluppatori che non ho ancora capito bene.Controllo per null in Constructor

public MyConstructor(Object myObject) 
{ 
    if (myObject == null) 
     throw new ArgumentNullException("myObject is null."); 
    _myObject = myObject; 
} 

Sembra quasi superfluo effettuare questo controllo. Ma penso che sia perché non capisco completamente quali sono i vantaggi di fare questo controllo. Sembra che un'eccezione di riferimento null verrebbe comunque generata? Probabilmente ho torto, mi piacerebbe davvero sentire alcune riflessioni su di esso.

Grazie.

+0

Cosa si sta facendo non è necessario, è possibile verificare per assicurarsi che prima di fare riferimento all'oggetto, che non fosse nullo. Naturalmente convalidare ciò che userete quando il vostro oggetto è intializzato è un approccio molto valido. –

+2

@Ramhound: questo è un approccio comune quando si utilizzano quadri DI come StructureMap in cui non si ha necessariamente il controllo diretto su ciò che viene passato al costruttore. Se la tua classe è inutile senza 'myObject' e questo è l'unico posto per inizializzarlo, allora ha senso gettare le eccezioni il prima possibile in modo da conoscerle. In un'applicazione web a esecuzione prolungata potresti non essere a conoscenza del problema fino a quando qualcuno non chiama un metodo che richiede l'oggetto. –

risposta

17

Al compilatore, null è un argomento legittimo del costruttore.

La classe potrebbe essere in grado di gestire un valore nullo per myObject. Ma se non è possibile - se la tua classe si interromperà quando myObject è nullo - allora il controllo nel costruttore ti permetterà di fail fast.

+0

Molto ben spiegato. Mi è particolarmente piaciuto il termine "fallire veloce". Grazie per gli approfondimenti. – jsmith

+2

+1 Wow, questa è una carta eccellente. Grazie per il link. –

1

Il compilatore non ha idea del valore di un oggetto, quindi è necessario verificarlo in fase di esecuzione per assicurarsi che non venga chiamato con un valore nullo.

Dipende anche dalla vostra particolare soluzione. Non hai bisogno di lanciare l'eccezione, la butterei solo se non puoi avere quel valore essere nullo, e se è nullo, questo è un caso eccezionale.

1

Penso che non sia possibile dire in generale se il controllo di null è necessario o meno. Dipende piuttosto dal fatto che si possa vivere con variabili con valori nulli o meno. Null non è di per sé uno stato negativo. Potresti avere situazioni in cui è consentito che una variabile sia nullo e altra dove non lo è.

Chiedetevi se ha senso consentire valori nulli o meno e progettare di conseguenza il costruttore.

3

Passare un oggetto null in molti casi è perfettamente legale: per questa classe l'implementatore vuole assicurarsi che non sia possibile creare un'istanza della classe senza passare un'istanza valida Object, quindi non ci devono essere controlli in seguito on - è una buona pratica assicurarla il prima possibile, che sarebbe nel costruttore.

0

È necessario verificare esplicitamente null perché il compilatore non lo sa, ma anche perché null può essere un argomento valido.

0

Il vantaggio è che l'eccezione verrà lanciata al momento della costruzione dell'oggetto, in modo da poter facilmente individuare quale parte del codice è il colpevole. Se il codice richiede valore non nullo myobject e non convalida nel costruttore, il NullReferenceException saranno gettati quando si utilizza myObject_ e si dovrà risalire manualmente per vedere chi ha inviato quel valore nullo in.

1

È possibile implementare un semplice metodo di estensione ThrowIfNull per ridurre il codice che si scrive ogni volta. Jon Skeet ne ha parlato nel suo blog e nell'articolo SO di riferimento here.

+0

Il link del blog è rotto, ma credo che questo sia lo stesso articolo: http://codeblog.jonskeet.uk/2009/12/09/quot-magic-quot-null-argument-testing/comment-page-1/ –

2

se sotto 4.0 è possibile effettuare le seguenti operazioni:

public ctor(IEnjection ninjaWeapon) 
{ 
    Contract.Requires<ArgumentNullException>(ninjaWeapon != null); 
    this.deadlyWeaponary.Add(ninjaWeapon); 
} 

se in una versione precedente, fare riferimento al Microsoft.Contract a fare la stessa cosa.

+1

+1 per l'uso di ninjaWeapon – ninjasense