2015-06-03 16 views
17

Il seguente banco di prova genera un'eccezione di riferimento null quando tenta di assegnare Id a un oggetto che è null, poiché al codice manca la "nuova R" prima dell'inizializzatore dell'oggetto.Perché questo inizializzatore di oggetti nidificati genera un'eccezione di riferimento null?

Perché non viene rilevato dal compilatore? Perché è permesso, in quali casi d'uso sarebbe un costrutto significativo?

[TestClass] 
public class ThrowAway 
{ 
    public class H 
    { 
     public int Id { get; set; } 
    } 

    public class R 
    { 
     public H Header { get; set; } 
    } 

    [TestMethod] 
    public void ThrowsException() 
    { 
     var request = new R 
         { 
          Header = 
          { 
           Id = 1 
          }, 
         }; 
    } 
} 
+0

È necessario inizializzare la proprietà Header dell'oggetto R. 'var request = new R {Header = new H {Id = 1}}; – Styxxy

+3

Domanda molto interessante ... non è nemmeno chiaro se il compilatore stia facendo un cast o cosa ... – xanatos

+3

Domanda molto interessante, ma titolo estremamente povero secondo me. Prenderesti in considerazione la possibilità di cambiarlo con l'attuale domanda che stai facendo? – julealgon

risposta

18

Il compilatore non dare un avvertimento, perché si potrebbe avere:

public class R 
{ 
    public H Header { get; set; } 

    public R() 
    { 
     Header = new H(); 
    } 
} 

così Header potrebbe essere inizializzato da qualcuno/qualcosa. Risolvere se qualcuno/qualcosa inizializzare Header è un problema complesso (probabilmente simile al problema della terminazione) ... Non è una cosa che un compilatore vuole risolvere per voi :-)

Dalle specifiche C#:

Un inizializzatore di membro che specifica un inizializzatore di oggetti dopo il segno di uguale è un inizializzatore di oggetti nidificati, ovvero un'inizializzazione di un oggetto incorporato. Invece di assegnare un nuovo valore al campo o alla proprietà, le assegnazioni nell'inizializzatore dell'oggetto nidificato vengono trattate come assegnazioni ai membri del campo o della proprietà. Gli inizializzatori di oggetti nidificati non possono essere applicati a proprietà con un tipo di valore o a campi di sola lettura con un tipo di valore.

Siamo nel caso di inizializzatore nidificato e vediamo la parte in grassetto. Non lo sapevo

Ora, si noti che new R { } è, per C# spec, un 7.6.10.1 Object creation expressions seguito da un object-initializer, mentre il Header = { } è un "puro" 7.6.10.2 Object initializers.

+1

La stessa domanda per l'altro post qui - perché ha permesso l'intestazione = {Id = 1} '? Questo sembra assolutamente sbagliato, vero? – Andrei

+0

@Andrei Almeno ho spiegato il * Perché questo non viene rilevato dal compilatore? * :-) – xanatos

+0

Scusa, non riesco ancora a capirlo. Non sto cercando di discutere, sono solo molto curioso di me stesso. Il compilatore avrebbe dovuto fallire su tale sintassi, non importa se c'è l'inizializzazione in ctor, giusto? – Andrei

Problemi correlati