2009-06-18 13 views

risposta

13

il compilatore utilizza ancora l'istruzione newarr iL, così il CLR sarà ancora inizializzare l'array.

L'inizializzazione della raccolta è solo Magia del compilatore: il CLR non ne sa nulla, quindi supporrà che debba ancora fare lo sdoganamento.

Tuttavia, questo dovrebbe essere veramente, molto veloce - è solo la cancellazione della memoria. Dubito che sia un sovraccarico significativo in molte situazioni.

+0

Interessante. Mi chiedo se questo approccio di "cancellazione della memoria" all'inizializzazione dell'array sia uno dei motivi per cui le struct non supportano i costruttori predefiniti di default o gli inizializzatori dei membri. Complicerebbe l'inizializzazione dell'array. – LBushkin

+1

Sì, questo è molto. In effetti, le strutture in IL * do * supportano i costruttori senza parametri, ma verranno chiamate solo in determinate situazioni. –

+0

Vedere http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types-and-parameterless-constructors.aspx per ulteriori informazioni. –

10

prova rapida:

 string[] arr1 = 
     { 
      "A","B","C","D" 
     }; 
     arr1.GetHashCode(); 

     string[] arr2 = new string[4]; 
     arr2[0] = "A"; 
     arr2[1] = "B"; 
     arr2[2] = "C"; 
     arr2[3] = "D"; 

     arr2.GetHashCode(); 

risultati in questo IL (nota, sono entrambi identici)

IL_0002: newarr  [mscorlib]System.String 
    IL_0007: stloc.2 
    IL_0008: ldloc.2 
    IL_0009: ldc.i4.0 
    IL_000a: ldstr  "A" 
    IL_000f: stelem.ref 
    IL_0010: ldloc.2 
    IL_0011: ldc.i4.1 
    IL_0012: ldstr  "B" 
    IL_0017: stelem.ref 
    IL_0018: ldloc.2 
    IL_0019: ldc.i4.2 
    IL_001a: ldstr  "C" 
    IL_001f: stelem.ref 
    IL_0020: ldloc.2 
    IL_0021: ldc.i4.3 
    IL_0022: ldstr  "D" 
    IL_0027: stelem.ref 
    IL_0028: ldloc.2 
    IL_0029: stloc.0 
    IL_002a: ldloc.0 
    IL_002b: callvirt instance int32 [mscorlib]System.Object::GetHashCode() 
    IL_0030: pop 
    IL_0031: ldc.i4.4 
    IL_0032: newarr  [mscorlib]System.String 
    IL_0037: stloc.1 
    IL_0038: ldloc.1 
    IL_0039: ldc.i4.0 
    IL_003a: ldstr  "A" 
    IL_003f: stelem.ref 
    IL_0040: ldloc.1 
    IL_0041: ldc.i4.1 
    IL_0042: ldstr  "B" 
    IL_0047: stelem.ref 
    IL_0048: ldloc.1 
    IL_0049: ldc.i4.2 
    IL_004a: ldstr  "C" 
    IL_004f: stelem.ref 
    IL_0050: ldloc.1 
    IL_0051: ldc.i4.3 
    IL_0052: ldstr  "D" 
    IL_0057: stelem.ref 
    IL_0058: ldloc.1 
    IL_0059: callvirt instance int32 [mscorlib]System.Object::GetHashCode() 
+0

+1 Per il test. –

1

ho fatto un breve test su instantianting un array utilizzando la sintassi si descrive e trovato che l'istanziazione con valori non predefiniti richiedeva circa 2,2 volte più dell'istantianizzazione con i valori predefiniti.

Quando passavo e creavo un'istanza con valori predefiniti, ci vuole circa lo stesso tempo.

Infatti, quando ho guardato il decompilare, sembra che ciò che accade è l'array inizializzato, e quindi viene popolato con qualsiasi valore che non sia il default.

Instantiating con valori non predefiniti:

  bool[] abPrimes = new[] { 
       true, true 
      }; 
0000007e mov   edx,2 
00000083 mov   ecx,79114A46h 
00000088 call  FD3006F0 
0000008d mov   dword ptr [ebp-64h],eax 
00000090 mov   eax,dword ptr [ebp-64h] 
00000093 mov   dword ptr [ebp-54h],eax 
00000096 mov   eax,dword ptr [ebp-54h] 
00000099 cmp   dword ptr [eax+4],0 
0000009d ja   000000A4 
0000009f call  76A9A8DC 
000000a4 mov   byte ptr [eax+8],1 
000000a8 mov   eax,dword ptr [ebp-54h] 
000000ab cmp   dword ptr [eax+4],1 
000000af ja   000000B6 
000000b1 call  76A9A8DC 
000000b6 mov   byte ptr [eax+9],1 
000000ba mov   eax,dword ptr [ebp-54h] 
000000bd mov   dword ptr [ebp-40h],eax 

un'istanza con valori di default:

bool[] abPrimes2 = new[] { 
       false, false 
      }; 
000000c0 mov   edx,2 
000000c5 mov   ecx,79114A46h 
000000ca call  FD3006F0 
000000cf mov   dword ptr [ebp-68h],eax 
000000d2 mov   eax,dword ptr [ebp-68h] 
000000d5 mov   dword ptr [ebp-54h],eax 
000000d8 mov   eax,dword ptr [ebp-54h] 
000000db mov   dword ptr [ebp-5Ch],eax 
0

Non è possibile evitare l'inizializzazione ogni slot matrice sul valore predefinito, almeno nel livello IL.

La stringa è una CLASSE, non una struttura.

Ciò significa che A, B, C, D e il sarray potrebbero essere memorizzati in qualsiasi posizione. A, B, C e D potrebbero essere prelevati dal pool Intern, affinché il riferimento all'oggetto possa essere dinamico.

Ma credo che il JIT potrebbe essere abbastanza intelligente da ridurre la metà di queste spese generali.

PS. L'ottimizzazione prematura è la radice di tutti i mali.