2013-06-26 10 views
9

Ho appena trovato un codice strano per me nel libro di Jeffrey Richter (CLR tramite C# 4.0, pagina 257) e ho frainteso il motivo per cui funziona così.get e set fraintendimento nell'inizializzazione: Jeffrey Richter, CLR via C#

public sealed class Classroom 
    { 
     private List<String> m_students = new List<String>(); 
     public List<String> Students { get { return m_students; } } 

     public Classroom() { } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Classroom classroom = new Classroom { 
       Students = { "Jeff", "Kristin" } 
      }; 

      foreach (var student in classroom.Students) 
       Console.WriteLine(student); 
     } 
    } 

Risultato:

Jeff 
Kristin 

Come potete vedere, abbiamo una proprietà di accesso di nome 'studenti', che ha solo getter (! Non Palleggiatrice), ma in funzione 'principale', quando vorremmo inizializzare variabile 'classe', abbiamo l'inizializzazione campo di tipo 'aula' 'studenti:

Classroom classroom = new Classroom { 
    Students = { "Jeff", "Kristin" } 
}; 

ho sempre pensato che quando una variabile in 'sul lato sinistro' di espressione (int i = 1), quindi il compilatore dovrebbe accedere alla funzione setter e quando in 'right-side' (int x = i + 2) alla funzione getter.

Perché nel codice di Jeffrey il comportamento è così interessante (potrebbe essere solo per me? Scusa se è così).

risposta

22

Dalla sezione 7.6.10.2 del C# 5 spec:

Un inizializzatore membro che specifica un inizializzatore collezione dopo il segno di uguale è una di inizializzazione di una collezione incorporata. Invece di assegnare una nuova raccolta al campo o alla proprietà, gli elementi forniti nell'inizializzatore vengono aggiunti alla raccolta a cui fa riferimento il campo o la proprietà. Il campo o la proprietà devono essere di un tipo di raccolta che soddisfi i requisiti specificati in §7.6.10.3.

Quindi questo codice:

Classroom classroom = new Classroom { 
    Students = { "Jeff", "Kristin" } 
}; 

è equivalente a:

Classroom tmp = new Classroom(); 
tmp.Students.Add("Jeff"); 
tmp.Students.Add("Kristin"); 
Classroom classroom = tmp; 

In sostanza, = all'interno di un inizializzatore oggetto non è esattamente la stessa di un istruzione di assegnazione stand-alone.

EDIT: Questo codice

Classroom classroom = new Classroom { 
    Students = new List<string> { "Jeff", "Kristin" } 
}; 

non riuscirebbe a compilare, come quella sarebbe provare a chiamare un setter per Student.

+1

Dov'è il badge per la risposta rapida che migliora le modifiche? – Michael

+0

Vale la pena notare che 'Studenti = nuova lista ()' darebbe un errore in fase di compilazione in quanto uno, a prima vista, potrebbe inizialmente prevedere in questo altro caso? –

+1

Questa conoscenza ha soddisfatto la mia quota "Edifying C# fact of the day". – Chris