2013-08-02 6 views
7

sto facendo una revisione del codice e ha trovato una linea in cui uno dei nostri sviluppatori è la creazione di un oggetto utilizzando un inizializzatore oggetto vuoto come questo:Ci sono degli svantaggi nell'uso di un inizializzatore di oggetti vuoto?

List<Floorplan> floorplans = new List<Floorplan> { }; 

non so perché avrebbe un'istanza in questo modo, piuttosto che :

List<Floorplan> floorplans = new List<Floorplan>(); 

Ci sono dei lati negativi per l'istanziazione degli oggetti utilizzando gli inizializzatori di oggetti vuoti? Oltre ad essere stilisticamente incoerente, voglio sapere se c'è un motivo per evitare questo approccio. Qualcosa mi dice questo odore ma voglio essere sicuro prima di dire qualcosa.

+2

'var floorplans = new List ();' è il migliore IMO. Non ci sono aspetti negativi. –

+6

In caso di dubbi controllare l'IL. Gli inizializzatori della raccolta sono semplicemente zucchero sintattico. –

+2

FYI - ReSharper, per impostazione predefinita, genera un avviso sull'inizializzatore dell'oggetto vuoto. –

risposta

10

Il risultato compilato è lo stesso.

Il seguente C#:

static void Main() 
{ 
    var x = new List<int>(); 
    var y = new List<int> { }; 
} 

compila in quanto segue IL:

.method private hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2050 
    // Code size 14 (0xe) 
    .maxstack 1 
    .entrypoint 
    .locals init (
     [0] class [mscorlib]System.Collections.Generic.List`1<int32> x, 
     [1] class [mscorlib]System.Collections.Generic.List`1<int32> y 
    ) 

    IL_0000: nop 
    IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() 
    IL_0006: stloc.0 
    IL_0007: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() 
    IL_000c: stloc.1 
    IL_000d: ret 
} // end of method Program::Main 

Se si aggiunge un valore alle collezioni:

static void Main() 
{ 
    var x = new List<int>(); 
    x.Add(1); 
    var y = new List<int> { 1 }; 
} 

Questa è la risultante IL:

.method private hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2050 
    // Code size 32 (0x20) 
    .maxstack 2 
    .entrypoint 
    .locals init (
     [0] class [mscorlib]System.Collections.Generic.List`1<int32> x, 
     [1] class [mscorlib]System.Collections.Generic.List`1<int32> y, 
     [2] class [mscorlib]System.Collections.Generic.List`1<int32> '<>g__initLocal0' 
    ) 

    IL_0000: nop 
    IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() 
    IL_0006: stloc.0 
    IL_0007: ldloc.0 
    IL_0008: ldc.i4.1 
    IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0) 
    IL_000e: nop 
    IL_000f: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor() 
    IL_0014: stloc.2 
    IL_0015: ldloc.2 
    IL_0016: ldc.i4.1 
    IL_0017: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0) 
    IL_001c: nop 
    IL_001d: ldloc.2 
    IL_001e: stloc.1 
    IL_001f: ret 
} // end of method Program::Main 

Questo mostra come gli inizializzatori di raccolta sono solo zucchero di sintassi. Poiché gli inizializzatori di raccolta non erano originariamente parte di C#, penso che le persone siano più abituate alla sintassi del costruttore. Se mi sono imbattuto in un codice che utilizzava un inizializzatore di raccolta vuoto, mi chiedo perché, ma certamente non ha alcun problema di leggibilità. Se uno è abbastanza intelligente da capire il codice, allora {} vs () non dovrebbe essere così sconvolgente da minare la capacità di una persona di comprendere ciò che il codice sta facendo.Si tratta di una questione di opinione. Fai quello su cui la tua squadra è d'accordo, e se sei solo tu, allora usalo per i tuoi cuori.

+0

+1 per approfondire risposta e spiegazione. – evanmcdonnal

1

Non vi è alcun motivo per cui l'inizializzazione { } debba essere utilizzata lì, quindi direi di rimuoverla. Lo sviluppatore sta utilizzando l'inizializzatore della raccolta statica. L'unico motivo per cui lo fai è che puoi iniziare la raccolta con alcuni oggetti, dato che non ce ne sono, non ha senso. Detto questo, il risultato sarà una raccolta vuota, proprio come se chiamasse normalmente il costruttore.

+0

Ma non ci sarebbe una differenza nella capacità interna? – Esailija

+0

@Esailija è retorico? Ci potrebbe sicuramente essere, tuttavia, l'array sottostante non può avere una lunghezza pari a 0, quindi suppongo che ottenga la capacità predefinita. – evanmcdonnal

+0

No, solo una domanda per sfidare le ipotesi affrettate sul fatto che siano veramente le stesse. Non avevo davvero idea, ma avrebbe potuto essere una possibilità. – Esailija

3

In questo caso non ci sono aspetti negativi, ma è preferibile la leggibilità. Se non hai bisogno delle parentesi aggiuntive durante l'istanziazione, non usarle in modo semplice e chiaro.

Direi che preferisco la produttività. Molte delle risposte qui stanno andando più in profondità nel tentativo di rispondere a questa domanda. Anche se una tecnica fosse migliore dell'altra, stiamo parlando di ciò che è davvero una micro ottimizzazione.

1

Sono praticamente uguali, ma l'utilizzo del costruttore predefinito è più leggibile.

0

Ci sono molti commenti che dicono "il costruttore predefinito è più leggibile". Non c'è alcun motivo per supporre che () sia più (o meno) leggibile di {}, quindi stai effettivamente prendendo un sondaggio di opinione qui.

Se sei preoccupato per la correttezza, il codice del tuo collega va bene. Se sei preoccupato per gli standard di codifica, dovresti assicurarti che il codice sia cambiato in modo che corrisponda al tuo standard (qualunque sia lo standard).

+0

'Non c'è una buona ragione per supporre che() sia più (o meno) leggibile di {}' Non sono sicuro che sia vero. Ricorda che la sintassi dell'inizializzatore è stata appena introdotta in C# 3.0, penso, quindi c'è molto di più codice che usa la sintassi '()' e la sintassi '()' è confrontabile a ritroso. Questo potrebbe non avere importanza per tutti, ma i suoi due altri motivi per cui la scelta non è solo un "sondaggio d'opinione" – chollida

+1

"Just" in C# 3.0? Ciò significa che questa funzione ha 6 anni. Non ci sono buoni motivi per non usare nuove funzionalità, specialmente una come "nuova". –

+0

per favore non essere difensivo :) Tutto quello che intendevo era che alcune persone sono intrappolate targeting per versioni precedenti .Questo è solo un fatto di vita.Utilizzare questa funzione significa che hai ufficialmente abbandonato il supporto per le versioni precedenti.Questo potrebbe non essere importante per te, ma ogni sviluppatore dovrebbe essere a conoscenza dei compromessi che stanno facendo. – chollida

Problemi correlati