2010-05-09 16 views
17

Stavo usando Reflector per esaminare l'implementazione di String.Format e avevo sempre avuto l'impressione che gli overload di String.Format che richiedevano 1, 2 argomenti & 3 fossero versioni ottimizzate del metodo che accetta un array di oggetti. Tuttavia, ho scoperto che internamente creano un array di oggetti e poi chiamano un metodo che accetta un array di oggetti.Perché esistono sovraccarichi di String.Format?

1 arg

public static string Format(string format, object arg0) 
{ 
    if (format == null) 
    { 
     throw new ArgumentNullException("format"); 
    } 
    return Format(null, format, new object[] { arg0 }); 
} 

2 args

public static string Format(string format, object arg0, object arg1) 
{ 
    if (format == null) 
    { 
     throw new ArgumentNullException("format"); 
    } 
    return Format(null, format, new object[] { arg0, arg1 }); 
} 

3 args

public static string Format(string format, object arg0, object arg1, object arg2) 
{ 
    if (format == null) 
    { 
     throw new ArgumentNullException("format"); 
    } 
    return Format(null, format, new object[] { arg0, arg1, arg2 }); 
} 

oggetto array

public static string Format(string format, params object[] args) 
{ 
    if ((format == null) || (args == null)) 
    { 
     throw new ArgumentNullException((format == null) ? "format" : "args"); 
    } 
    return Format(null, format, args); 
} 

Internamente tutti finiscono con lo stesso codice e in modo da utilizzare il 1, 2 & 3 versioni argomento non più veloce della versione oggetto array sono.

Quindi la mia domanda è - perché esistono?

Quando si utilizza la versione oggetto matrice con un elenco separato di valori, il compilatore converte automaticamente i parametri in un array oggetto a causa della/ParamArray parola chiave params che è essenzialmente quello che i 1, 2 & 3 versioni fanno, quindi sembrano ridondanti. Perché i progettisti del BCL hanno aggiunto questi sovraccarichi?

risposta

7

Uno dei motivi, come menziona Hans, è che la creazione di un array è un sovraccarico non necessario nei casi più comuni di formattazione di una stringa. Ciò consente di risparmiare spazio nel file EXE.

Un'altra ragione è che non tutte le lingue supportano le funzioni variadic (uso di params in C#). Ciò consente agli utenti di tali lingue di evitare la creazione di array per i casi più comuni di formattazione delle stringhe. Ciò consente di risparmiare molto per le lingue che non hanno una sintassi semplice per la creazione e l'inizializzazione di array.

+0

Buoni punti! Questo ha perfettamente senso per la loro esistenza. – GiddyUpHorsey

+0

"la creazione di un array è un sovraccarico non necessario" L'array viene creato all'interno del metodo come è diverso in termini di "overhead"? –

+1

@ChrisMarisic: Non è l'uso della memoria o il sovraccarico di GC della creazione degli array che è il problema; sono gli opcode aggiuntivi. Chiamare 'string.Format' con una sola sostituzione di stringa richiede solo 3 opcode IL, mentre richiederebbe 10 codici operativi se il sovraccarico non esistesse. Ogni parametro aggiuntivo richiede solo 1 opcode in più se può utilizzare un overload, rispetto a 4 altri opcode se utilizza un array. Dal momento che un metodo non può essere in linea se si tratta di troppi codici operativi, ciò ha importanti implicazioni. – Gabe

3

Stai dimenticando il codice nell'app richiesta per effettuare la chiamata. Creare l'array e riempirlo richiede molto più IL che solo il superamento di 3 arg.

+0

Hai assolutamente ragione. Non l'avrei considerato. Immagino si possa dire che questi metodi ottimizzano le dimensioni del codice chiamante piuttosto che le prestazioni che ho sempre pensato fossero lì per. – GiddyUpHorsey

+0

Quindi i sovraccarichi hanno senso se lo si chiama in IL diretto? –