2009-06-26 9 views
7

So che le stringhe sono immutabili, quindi nel momento in cui modifichi il valore di un riferimento di stringa, .NET crea una nuova stringa sull'heap.VB.NET: Se si passa una stringa ByVal in una funzione ma non si modifica la stringa, è necessario avere una o due stringhe in memoria?

Ma cosa succede se non si modifica il valore di un riferimento di stringa; piuttosto, è sufficiente passarlo in una funzione ByVal - questa operazione copia anche il valore della stringa sull'heap? La mia inclinazione è "no", ma mi piacerebbe confermare.

Ad esempio:

Public Function IsStringHello(ByVal test As String) As Boolean 
    Return (String.Compare(test, "Hello") = 0)  
End Function 

programma chiamante:

Dim myWord as String = "Blah" 
Dim matchesHello as Boolean = IsStringHello(myWord) 

So passando myWord per valore fa una copia del di riferimento a "Blah", ma dato che non hanno cercato di cambia la stringa stessa, creerebbe un'altra copia della stringa sull'heap?

+0

Perché le persone confrontano le stringhe in questo modo strano ... http://stackoverflow.com/questions/859005/string-comparison-performance/859078 – Dario

+1

Utilizzo di String.Compare consente di specificare la distinzione tra maiuscole e minuscole. Questo potrebbe essere più chiaro delle stringhe maiuscole prima di confrontarle. –

risposta

9

A proposito, l'internamento delle stringhe non ha nulla a che fare con questo. La regola per il passaggio dei parametri alle funzioni è la stessa per tutti i tipi di riferimento (e in realtà tutti i tipi), indipendentemente dal modo in cui sono gestiti internamente.

La regola è semplice e vi hanno dichiarato in modo corretto: passare da copie di valore della di riferimento, non il bersaglio . Qui non viene copiato nessuno spazio heap.

+0

interning non è direttamente correlato. Hai detto: la regola è la stessa per tutti i tipi di riferimento (e in realtà tutti i tipi), indipendentemente da come sono gestiti internamente - penso che tu lo dica per la copia di riferimento e non per l'interning. destra? – shahkalpesh

+0

Ah, giusto. Ho cancellato la dichiarazione. –

4

No. utilizza ancora la copia del riferimento in "Blah".
Cosa ti fa pensare, lo sarà?

Su una nota laterale, la stringa è internata.

string s = "hello"; 
string t = "hello"; 

s & t entrambe si riferiscono alla stessa stringa (perché è internato). Se modifichi sot, creerà una nuova stringa, quindi.

+0

Ho avuto uno strano (sciocco?) Pensiero che forse semplicemente facendo una copia di un riferimento a un oggetto immutabile ha causato anche una copia dell'oggetto stesso. Ho fortemente sospettato che non fosse così, ma volevo confermarlo. Grande nota a margine sul "tirocinio" degli archi - non lo sapevo. Grazie! –

+0

Stringa * le costanti * sono internate. Le stringhe che crei in altri modi non sono internate. –

+0

@JonSkeet - ahhh ... così nella risposta di shahkalpesh sopra dove assegniamo due riferimenti alla stessa stringa * letterale * non significa che si riferiscono alla stessa stringa sull'heap? –

0

È breve, no. Passa un riferimento alla stringa. Solo un'istanza della stringa stessa.

0

string è un tipo di riferimento. Se lo passi per valore, ciò che stai passando è il valore del riferimento.

L'unico modo per ottenere un'altra copia nell'heap è modificare il valore della variabile.

2

Il passaggio di oggetti ByVal crea una copia del puntatore , non l'oggetto stesso. Ecco una dimostrazione:

Module Module1 
    Dim original As String = "Hello world" 

    Sub PassByReferenceTest(ByVal other As String) 
     Console.WriteLine("object.ReferenceEquals(original, other): {0}", _ 
      Object.ReferenceEquals(original, other)) 
    End Sub 

    Sub Main() 
     PassByReferenceTest(original) 
     Console.ReadKey(True) 
    End Sub 
End Module 

Questo programma stampa il seguente:

object.ReferenceEquals(original, other): True 

Così, la stringa originale e la stringa siamo passati per valore esistono allo stesso indirizzo in indirizzo di memoria. Non stai facendo una copia della stringa stessa.

0

Una variabile di tipo System.String contiene effettivamente un "ID oggetto".Supponiamo che Object #1934 sia una stringa con i caratteri "Blah" e che tu dici Dim myWord As String = "Blah". Il compilatore memorizzerà quindi Object #1934 in myWord. Chiamando il numero IsStringHello(myWord), la chiamata verrà quindi chiamata con il parametro test uguale a Object #1934. Nel tuo esempio, ci sarebbero due variabili di tipo System.String in memoria - myWord e test, ed entrambi avrebbero il contenuto Object #1934.