2012-05-19 18 views
6

So che string è immutabile e StringBuilder è modificabile. Ma qualcuno può spiegare la seguente uscita del codice? Poiché entrambi sono tipi di riferimento, perché hanno risultati diversi?Qual è la differenza tra string e StringBuilder?

String s1 = "hello"; 
String s2 = "hello"; 
Console.WriteLine(s1 == s2); //true 
Console.WriteLine(Object.ReferenceEquals(s1, s2)); //true 

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 
Console.WriteLine(sb1 == sb2); //false 
Console.WriteLine(Object.ReferenceEquals(sb1, sb2)); //false 
+1

si sta confrontando due diversi riferimenti 'StringBuilder' oggetti. Sono due oggetti separati. – birryree

+0

+1, non solo per una domanda eccellente, ma per chiederlo in modo così chiaro, con un campione completo di codice commentato perfettamente. –

+1

Questa domanda in realtà non ha nulla a che fare con 'StringBuilder'. Si tratta in realtà di "perché due variabili stringa inizializzate con due stringhe letterali che contengono la stessa sequenza di caratteri sono paragonabili ad essere lo stesso oggetto"? –

risposta

10

Dal entrambi sono tipi di riferimento, perché hanno risultati diversi?

Perché gli oggetti string sono altamente ottimizzati. In particolare, poiché sono immutabili, possono essere internati dal compilatore per impedire la duplicazione.

Se si dispone di due diversi oggetti string che rappresentano entrambi la stessa stringa di caratteri (come nell'esempio), il compilatore lo riconoscerà e manterrà solo un'istanza dell'oggetto stringa effettivo.

Il risultato è che entrambi gli oggetti s1 e s2 sono effettivamente lo stesso oggetto per quanto riguarda il compilatore e persino fanno riferimento alla stessa posizione nella memoria.

Questa contabilità avviene dietro le quinte in una cosa chiamata "tavolo degli stagisti", ma non è davvero qualcosa di cui ti devi preoccupare. L'importante è che tutti i valori letterali stringa siano internati per impostazione predefinita dal compilatore.

Lo stesso tipo di cosa non corrisponde a per gli oggetti StringBuilder, perché non sono immutabili. Sono progettati per consentire di modificare un oggetto stringa e, in quanto tali, le ottimizzazioni non hanno molto senso. Ecco perché gli oggetti sb1 e sb2 vengono effettivamente visti come due oggetti diversi.

La regola generale è piuttosto semplice: utilizzare string per impostazione predefinita o quando si desidera una singola stringa di caratteri immutabile. Utilizzare solo StringBuilder quando si desidera modificare la stessa stringa più volte, ad esempio in un ciclo o in un'altra sezione di codice relativamente breve.

lettura Rilevante: Optimizing C# String Performance

+0

Questo ha perfettamente senso. – GLP

1

Quando si sta facendo quanto segue si confrontano non due oggetti diversi StringBuilder i loro valori:

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 
Console.WriteLine(sb1 == sb2); //false 

In questo modo è possibile confrontare i loro valori:

Console.WriteLine(sb1.ToString() == sb2.ToString()); 
4

Quando si dichiara

String s1 = "hello"; 
String s2 = "hello"; 

il compilatore è abbastanza intelligente per sapere che le due stringhe sono (e saranno sempre) identici, quindi memorizza "hello" solo una volta e crea s1 e s2 come alias per la stessa memoria fisica. Più tardi, quando testate per l'uguaglianza, i due sono uguali perché sono essenzialmente la stessa variabile.

D'altra parte, quando si dichiara

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 

il compilatore crea due variabili (perché entrambi sono mutabili, ma capita di essere inizializzato allo stesso valore).Copia la stringa "hello" in ognuna di esse, ma ora ci sono 2 copie, poiché ognuna potrebbe essere successivamente modificata. Quindi, anche se i loro contenuti sono gli stessi, sono 2 entità diverse che risiedono in differenti posizioni di memoria fisica, quindi i test per l'uguaglianza degli oggetti falliscono.

2

Per impostazione predefinita, quando vengono confrontati due oggetti di tipo di riferimento, il risultato è true solo se entrambi i riferimenti sono uguali, ciò significa che entrambi gli operandi devono fare riferimento alla stessa istanza dell'oggetto. Poiché gli oggetti a cui fa riferimento sb1 e sb2 sono due oggetti diversi, il risultato del confronto tra StringBuilders è falso.

classe String Ma la priorità operatore di uguaglianza in modo tale, che non si confronta gli oggetti dai loro riferimenti, ma dai loro valori, perché questo comportamento è molto intuitivo e atteso dai programmatori. Questo spiega perché s1 == s2 restituisce true.

Il motivo per cui Object.ReferenceEquals (s1, s2) restituisce anche true (anche se sembra che s1 e s2 faccia riferimento a diverse istanze di stringa) è chiamato string interning. Essa provoca che CLR mette tutte le occorrenze di identici stringhe letterali (come "hallo" e "hallo" nel tuo esempio) alla piscina interna di stringhe solo una volta per ogni applicazione, in modo che entrambi S1 e S2 in realtà fa riferimento alla stessa istanza di stringa "hallo" . Questo è possibile, perché le stringhe sono immutabili.

Problemi correlati