2010-10-27 13 views
52

Dato il codice qui sotto, qual è la differenza tra il modo in position0 viene inizializzato e il modo in cui viene inizializzato position1? Sono equivalenti? In caso contrario, qual è la differenza?Cosa fanno le parentesi dopo la nuova istruzione C#?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Position position0 = new Position() { x=3, y=4 }; 

     Position position1 = new Position(); 
     position1.x = 3; 
     position1.y = 4; 
    } 
} 

struct Position 
{ 
    public int x, y; 
} 

risposta

41

Inizializzatori di oggetti e di raccolta, utilizzati per inizializzare i campi su un oggetto.

http://msdn.microsoft.com/en-us/library/bb384062.aspx

Essi producono quasi equivalente IL. Jon Skeet ha la risposta su ciò che sta realmente accadendo.

+1

Gran parte della verità. Inserita la mia risposta ... ha visto la sua risposta, l'ha modificata per indicare la sua risposta. –

+0

Jon Skeet sembra rispondere a tutte le domande su questo sito :) Non vedo l'ora di leggere il suo nuovo libro (se mai verrà pubblicato) – Bryan

1

Questi sono completamente equivalenti. Il compilatore in realtà trasforma solo la prima versione nella seconda.

L'unica differenza tra i due è che con il primo, si può fare belle si assottiglia, come passare la versione inizializzata ad un metodo:

DoSomethingWithPoint(new Position() { x=3, y=4 }); 

Questo è molto più righe di codice rispetto al secondo di inizializzazione esempio.

2

I suoi due esempi di codice genererà identici IL. (Almeno nelle versioni di Release)

5

Questo è un inizializzatore di oggetti e consente semplicemente di assegnare valori in una singola espressione. Ancora più importante, questo funziona anche all'interno di LINQ e per i tipi anonimi (altrimenti immutabili). Esiste anche una sintassi di inizializzazione della raccolta simile per gli elementi aggiuntivi alle nuove raccolte.

Si noti che esiste un problema di temporizzazione che può essere utile; con gli inizializzatori gli assegnamenti/tutti gli eventi accadono prima dello la variabile è assegnata, il che può aiutare a fermare altri thread vedendo un oggetto incompleto. Avresti altrimenti bisogno di una variabile aggiuntiva per ottenere lo stesso risultato.

+0

Joshua e Slaks hanno scritto che entrambi i modi di inizializzare 'Position' producono IL equivalente. Lo stai dicendo con tipi anonimi, otterrei un risultato diverso? –

+0

@ rice - sì: solo uno di loro avrebbe compilato :) –

1

Sono equivalenti, a parte uno è più facile da leggere rispetto all'altro.

Considera anche il caso in cui si desidera passare al nuovo oggetto lungo da qualche altra parte:

var aList = new List<Position>(); 
aList.Add(new Position() { x=3, y=4 }); 
51

Essi non sono del tutto equivalente - almeno non nel caso generale. Il codice utilizzando un inizializzatore oggetto è più vicino a questo:

Position tmp = new Position(); 
tmp.x = 3; 
tmp.y = 4; 
Position position1 = tmp; 

In altre parole, l'assegnazione alla variabile avviene solo dopo sono state impostate le proprietà. Ora, nel caso in cui dichiari una nuova variabile locale, ciò non ha alcuna importanza e il compilatore potrebbe ottimizzarlo sul tuo primo modulo. Ma logicamente, importa. Considerate:

Position p1 = new Position { x = 10, y = 20 }; 

p1 = new Position { x = p1.y, y = p1.x }; 

Se che ha fatto il compito di p1prima, che ci si finisce con 0 per entrambi p1.x e p1.y. Mentre questo è in realtà equivale a:

Position tmp = new Position(); 
tmp.x = 10; 
tmp.y = 20; 
Position p1 = tmp; 

tmp = new Position(); 
tmp.x = p1.y; // 20 
tmp.y = p1.x; // 10 
p1 = tmp; 

EDIT: Ho appena realizzato che si sta utilizzando una struttura piuttosto che una classe.Ciò potrebbe rendere alcune sottili differenze ... ma quasi certamente non dovresti usare una struttura mutevole per iniziare :)

2

Dimenticato di tutte le cose di IL, è solo una notazione abbreviata. Quello che stai facendo è questo:

a. In un caso si utilizza in modo esplicito il costruttore predefinito e quindi si impostano le due proprietà.

b. Nell'altro, stai usando la nuova sintassi di intializer che implicitamente fa fare al compilatore quello che hai fatto nel caso a.

Nonostante i sottotitoli IL, otterranno la stessa cosa per voi.

Problemi correlati