VB.NET: если я передаю String ByVal в функцию, но не изменяю строку, у меня есть одна или две строки в памяти? - PullRequest
7 голосов
/ 26 июня 2009

Я знаю, что строки являются неизменяемыми, поэтому, как только вы меняете значение ссылки на строку, .NET создает новую строку в куче.

Но что если вы не измените значение ссылки на строку; скорее вы просто передаете его в функцию ByVal - копирует ли эта операция также строковое значение в кучу? Я склоняюсь к «нет», но я хотел бы подтвердить.

Например:

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

Программа вызова:

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

Я знаю, что передача myWord по значению делает копию ссылки на "Бла", но, поскольку я не пытался изменить саму строку, будет ли она делать еще одну копию строки на куча?

Ответы [ 6 ]

9 голосов
/ 26 июня 2009

Кстати, интернирование строк совершенно не связано с этим. Правило для передачи параметров в функции одинаково для всех ссылочных типов (и действительно, для всех типов), независимо от того, как они управляются внутри.

Правило простое, и вы правильно его сформулировали: передача по значению копирует ссылку , а не target . Здесь не копируется пространство кучи.

4 голосов
/ 26 июня 2009

Нет. он все еще использует копию ссылки на "Blah".
Что заставляет вас думать, это будет?

На боковой ноте строки интернированы.

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

s & t оба ссылаются на одну и ту же строку (потому что она интернирована). Если вы измените s или t, он создаст новую строку, а затем.

2 голосов
/ 26 июня 2009

Передача объектов ByVal создает копию указателя , а не сам объект. Вот демонстрация:

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

Эта программа выводит следующее:

object.ReferenceEquals(original, other): True

Итак, исходная строка и строка, которую мы передали по значению, существуют по одному и тому же адресу в памяти. Вы не делаете копию самой строки.

0 голосов
/ 28 июня 2012

Переменная типа System.String эффективно содержит «идентификатор объекта». Предположим, что Object #1934 - это строка с символами "Blah", а вы говорите Dim myWord As String = "Blah". Компилятор сохранит Object #1934 в myWord. Вызов IsStringHello(myWord) вызовет вызов этой функции с параметром test, равным Object #1934. В вашем примере в памяти будет две переменные типа System.String - myWord и test, и обе будут содержать содержимое Object #1934.

0 голосов
/ 26 июня 2009

строка является ссылочным типом. Если вы передаете его по значению, то вы передаете значение ссылки.

Единственный способ получить другую копию в куче - это изменить значение переменной.

0 голосов
/ 26 июня 2009

Коротко, нет. Он передает ссылку на строку. Только один экземпляр самой строки.

...