2016-07-02 56 views
19

Ho trovato il codice su un sito Web che è il seguente.Qual è lo scopo della trasmissione in tipo "oggetto"?

string a = "xx"; 
string b = "xx"; 
string c = "x"; 
string d = String.Intern(c + c); 

Console.WriteLine((object)a == (object)b); // True 
Console.WriteLine((object)a == (object)d); // True 

Qui, qual è lo scopo di fusione in tipo di oggetto nuovamente dato a, b, d sono in sé gli oggetti di stringa?

+1

Assolutamente nessuno. System.String eredita da System.Object – misha130

+1

Non c'è bisogno di trasmettere ... –

+27

L'autore di quel codice vuole chiamare 'operator == (oggetto, oggetto)' (uguaglianza di riferimento) invece di (adattamento migliore, per quanto riguarda il sovraccarico la risoluzione è interessata) 'operator == (stringa, stringa)' (valore uguaglianza), quindi il cast. Le chiamate dell'operatore non sono polimorfiche, vengono risolte in fase di compilazione. Un'alternativa sarebbe chiamare 'object.ReferenceEquals()' senza il cast. –

risposta

24

Il compilatore C# cercherà di ottenere tutte le stringhe costanti in fase di compilazione. Questo è chiamato internamento stringa. Quindi, dopo che il codice generato a e sono riferimenti alla stessa stringa che contiene "xx".

È possibile controllare questo confrontando i loro riferimenti (gettandoli a oggetto e fare il controllo di uguaglianza o utilizzare object.ReferenceEquals). Tieni presente che l'operatore == per le stringhe confronta i loro valori e non i loro riferimenti.

Un'altra cosa da ricordare è che strings are immutable in .NET.

string a = "xx"; 
string b = "x" + "x"; // String interning here 
string c = string.Join("", new[] { "x", "x" }); // No interning here because it is evaluated at runtime 

Console.WriteLine((object)a == (object)b); // True. Reference check 
Console.WriteLine(a == b); // True. Value check 

Console.WriteLine((object)a == c); //False. Reference check. Described below 
Console.WriteLine(a == c); // True. Value check 

Quindi perché Console.WriteLine((object)a == c); fare un controllo di riferimento ?? Perché il compilatore sceglierà l'operatore == sull'oggetto che controlla l'uguaglianza di riferimento.


Quindi il punto di getto per fare obiezioni nella domanda è controllare se l'internamento di stringa funziona o meno. Supponendo che non ci sia interning al momento della compilazione.

string a = "xx"; 
string b = "xx"; 
string c = "x"; 
string d = String.Intern(c + c); 

Poi Console.WriteLine((object)a == (object)b); stampa su "False", perché a e b sono riferimenti per due diversa stringa in memoria, entrambi i quali sembrano "xx".

+0

L'interning deve essere esplicito quando si costruisce manualmente una stringa? (come nella domanda) –

+3

[Operatore ==] (http://referencesource.microsoft.com/#mscorlib/system/string.cs,661) verifica il valore per le stringhe. @Carl – dotctor

+0

@dotctor Ma questo non significherebbe in questo caso, come da spiegazione, riferimento di un riferimento uguale a b, che cambiando il valore di b dovrebbe comportare la modifica del valore di a? La stringa è un tipo di riferimento e ha un riferimento a un oggetto nell'heap? Le stringhe – Legends

6

Un'aggiunta alla risposta fornita: string (C# Reference)

Il classe System.String è un tipo di riferimento immutabile previsto libreria di classi .NET framework. Questa classe crea internamente una nuova stringa per qualsiasi azione di manipolazione delle stringhe. Il contenuto degli oggetti di questo tipo non cambia, sebbene la sintassi lo faccia apparire come come se i contenuti potessero essere modificati. Inoltre, la stringa viene utilizzata come chiave di tabella hash per il calcolo dei valori hash per evitare il rischio di che danneggia la struttura dei dati hash.

Esempio:

string a = "hello"; 
string b = "h"; 

// Append to contents of 'b' 
b += "ello"; 
// When you set the variable's b value to "hello", 
// this would result in changing the pointer 
// to the object in the HEAP the variable "a" is already pointing to 
// Result would be: (reference of a == reference of b) --> TRUE 
// b = "hello"; 

Console.WriteLine(a == b);      // value comparison 
Console.WriteLine((object)a == (object)b);  // reference comparison 
Console.WriteLine (object.ReferenceEquals(a,b)); // reference comparison without casting 

Risultato:

True 
False 
False 

Spiegazione:

questo creerà un nuovo oggetto:

string a = "hello"; 

Ciò creerà un altro oggetto:

string b = "h"; 

Ciò creerà ancora un altro scopo:

b += "ello"; 

Quanto segue creare un riferimento a un oggetto esistente, più precisamente, lo farà puntare allo stesso oggetto la variabile "a" punta a → "ciao".

string c = "hello"; 
Console.WriteLine (object.ReferenceEquals(a,c)); // --> TRUE 

Le stringhe sono immutable-- il contenuto di un oggetto stringa non può essere cambiato dopo l'oggetto viene creato, anche se la sintassi rende apparire come se si può fare questo. Ad esempio, quando si scrive questo codice, , il compilatore crea effettivamente un nuovo oggetto stringa per contenere la nuova sequenza di caratteri e il nuovo oggetto viene assegnato a b. La stringa "h" è quindi idonea per la garbage collection.

+2

Non si dovrebbe menzionare l'heap o lo stack perché questi sono dettagli di implementazione di .NET runtime e possono variare tra diverse versioni. [Heap and Stack] (https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/) – dotctor

+0

Mi riferisco all '"implementazione Microsoft di C# sul CLR". È solo una addizione alla tua risposta, per renderla forse più comprensibile ;-) – Legends

5

C# utilizza il token == per rappresentare tre operatori distinti: un operatore di uguaglianza-check sovraccaricabile (utilizzabile su tipologie di classi o tipi di valore se esistono sovraccarichi per i tipi esatti in questione), un non-sovraccaricabile riferimento-su identità controlla operatore (che richiede che entrambi gli operandi siano riferimenti di classe e richiede che i tipi non si escludano a vicenda) e un operatore null-check (che è utilizzabile con qualsiasi tipo di classe, tipo di valore nullable o generici che potrebbe essere uno dei sopra). Mentre la maggior parte delle forme di overloading sono definite in modo uniforme attraverso i linguaggi .NET, l'uso di un operatore per tutti e tre i tipi di uguaglianza non lo è. Altri linguaggi come VB.NET utilizzano un diverso token per il primo modulo (ad esempio in VB.NET, l'espressione (x = y) utilizza un overload di test di uguaglianza se ne viene definito uno o genera un errore di sintassi se non; (x Is y) test se e identificano la stessa istanza dell'oggetto senza considerare se esiste un operatore di uguaglianza sovraccarico).

Lo scopo dei cast a Object è quello di garantire che il token == venga interpretato come rappresentativo di un operatore di riferimento-identità-controllo piuttosto che un operatore di uguaglianza sovraccarico; tali lanci sono necessari solo per il modo in cui C implementa l'operatore == e non sarebbe necessario in altri linguaggi come VB.NET.

1

commento con il codice

Quindi, se i valori di “XX” sono stati fissati in fase di esecuzione tutti per lo stesso valore di “xx”, allora si otterrebbe diverso risultato falso dal momento che il compilatore non ha avuto la possibilità di fare il ottimizzazione in fase di esecuzione, anche se è lo stesso codice e valori di input in entrambi i casi, risultati diversi per precompilato vs runtime.

private void button1_Click(object sender, EventArgs e) 
{ 
    string a = "xx"; 
    string b = "xx"; 
    string c = "x"; 
    string d = String.Intern(c + c); 

    Console.WriteLine((object)a == (object)b); // True 
    Console.WriteLine((object)a == (object)d); // True 
} 

private void button2_Click(object sender, EventArgs e) 
{ 
    string a = textBox1.Text; //type in xx at runtime 
    string b = textBox2.Text; //type in xx at runtime 
    string c = textBox3.Text; //type in just "x" at runtime 
    string d = String.Intern(c + c); 

    Console.WriteLine((object)a == (object)b); // False with runtime values that have the same value 
    Console.WriteLine((object)a == (object)d); // False 
    Console.WriteLine(a == d); // True - the Equals Operator of the string works as expected still 
} 
Problemi correlati