Dal momento che non credo che le risposte qui riguardino tutto, vorrei fare una piccola aggiunta qui.
Console.WriteLine(string format, params object[] pars)
chiamate string.Format
. Il '+' implica la concatenazione di stringhe. Non penso che questo abbia sempre a che fare con lo stile; Tendo a mescolare i due stili a seconda del contesto in cui mi trovo.
Risposta breve
La decisione che stai affrontando ha a che fare con l'allocazione delle stringhe. Proverò a renderlo semplice.
Di 'che hai
string s = a + "foo" + b;
Se lo esegui, valuterà come segue:
string tmp1 = a;
string tmp2 = "foo"
string tmp3 = concat(tmp1, tmp2);
string tmp4 = b;
string s = concat(tmp3, tmp4);
tmp
qui non è in realtà una variabile locale, ma è temporanea per JIT (è inserita nello stack IL). Se si ldstr
inserisce una stringa nello stack (come in IL per i letterali), si inserisce un riferimento a un puntatore di stringa nello stack.
Nel momento in cui chiami concat
questo riferimento diventa un problema, perché non è disponibile alcun riferimento di stringa che contenga entrambe le stringhe. Ciò significa che .NET deve allocare un nuovo blocco di memoria e quindi riempirlo con le due stringhe. Il motivo per cui questo è un problema è perché l'allocazione è relativamente costosa.
Il che cambia la domanda in: Come è possibile ridurre il numero di concat
operazioni?
Quindi, la risposta approssimativa è: string.Format
per> 1 concat, '+' funzionerà bene per 1 concat. E se non ti interessa fare ottimizzazioni di micro-prestazioni, string.Format
funzionerà bene nel caso generale.
Una nota sulla cultura
E poi c'è qualcosa chiamato cultura ...
string.Format
ti consente di utilizzare CultureInfo
nella formattazione. Un semplice operatore '+' utilizza la cultura corrente.
Questa è un'osservazione particolarmente importante se stai scrivendo formati di file e f.ex. double
valori che 'aggiungi' a una stringa. Su macchine diverse, potresti finire con stringhe diverse se non le usi string.Format
con un esplicito CultureInfo
.
F.ex. considera cosa succede se cambi un '.' per un "," durante la scrittura del file con valori separati da virgola ... in olandese il separatore decimale è una virgola, quindi l'utente potrebbe semplicemente ricevere una sorpresa "divertente".
Risposta più dettagliata
Se non si conosce in anticipo la dimensione esatta della stringa, è consigliabile utilizzare una politica come questa per sovrallocare i buffer utilizzati. Lo spazio lento viene prima riempito, dopo di che i dati vengono copiati.
Crescere significa allocare un nuovo blocco di memoria e copiare i vecchi dati nel nuovo buffer. Il vecchio blocco di memoria può quindi essere rilasciato. A questo punto ottieni la linea di fondo: crescere è un'operazione costosa.
Il modo più pratico per farlo è utilizzare una politica di sovrallocazione. La politica più comune è quella di sovrallocare i buffer con potenze di 2. Naturalmente, devi farlo un po 'più intelligente di quello (poiché non ha senso crescere da 1,2,4,8 se sai già che hai bisogno di 128 caratteri ) ma ottieni l'immagine. La politica garantisce che non siano necessarie troppe operazioni costose che ho descritto sopra.
StringBuilder
è una classe che fondamentalmente sovralloca il buffer sottostante in potenze di due. string.Format
utilizza StringBuilder
sotto il cofano.
Questo rende la tua decisione un compromesso di base tra overallocate-and-append (-multiple) (w / wo culture) o semplicemente allocate-and-append.
string.Format
che non utilizza alcuna funzionalità di formattazione composita (cioè semplicemente semplice{0}
) e sostituirli con la concatenazione di stringhe notevolmente più veloce. Mi chiedo che una simile impresa sia realizzabile con un riscrittore di IL esistente come PostSharp.