VB.NET:如果我将字符串ByVal传递到函数中,但不更改字符串,那么内存中是否有一个或两个字符串?

VB.NET:如果我将字符串ByVal传递到函数中,但不更改字符串,那么内存中是否有一个或两个字符串?,vb.net,string,byref,byval,Vb.net,String,Byref,Byval,我知道字符串是不可变的,所以只要更改字符串引用的值.NET就会在堆上生成一个全新的字符串 但是,如果不更改字符串引用的值,该怎么办;相反,您只需将其传递到一个函数ByVal——此操作是否也复制堆上的字符串值?我倾向于“不”,但我想确认一下 例如: Public Function IsStringHello(ByVal test As String) As Boolean Return (String.Compare(test, "Hello") = 0) End Function

我知道字符串是不可变的,所以只要更改字符串引用的值.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
会将引用的副本复制到“Blah”,但由于我没有尝试更改字符串本身,它会在堆上复制另一个字符串吗?

否。它仍然将引用的副本复制到“Blah”。
你怎么会这样想呢

在旁注中,字符串是插入的

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

科技和技术都是指同一个字符串(因为它是内部的)。如果修改s或t,它将创建一个新字符串。

很短,否。它将向字符串传递一个引用。字符串本身只有一个实例。

顺便说一句,字符串内部处理与此完全无关。将参数传递给函数的规则对于所有引用类型(实际上是所有类型)都是相同的,无论它们是如何在内部管理的


规则很简单,您已经正确地说明了这一点:按值传递复制引用,而不是目标。此处不复制堆空间。

字符串是引用类型。如果按值传递,则传递的是引用的值


在堆上获得另一个副本的唯一方法是更改变量的值。

通过val传递对象会创建指针的副本,而不是对象本身。下面是一个演示:

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

所以,原始字符串和我们通过值传递的字符串存在于内存地址中的同一地址。您没有复制字符串本身。

类型为
System.string的变量有效地保存“对象ID”。假设
Object#1934
是一个带有字符
“Blah”
的字符串,您说
Dim myWord为string=“Blah”
。然后,编译器将
Object#1934
存储到
myWord
中。调用
IsStringHello(myWord)
将导致调用该函数,其
test
参数等于
Object 35; 1934
。在您的示例中,内存中会有两个类型为
System.String
的变量--
myWord
test
,它们都会保存
对象的内容#1934

我有一个奇怪的想法(愚蠢的?)。可能仅仅复制一个不可变对象的引用也会导致对象本身的复制。我强烈怀疑事实并非如此,但我想证实。关于弦的“实习”的好的旁注——我不知道。谢谢字符串常量被插入。您以其他方式创建的字符串不会被占用。@JonSkeet-ahhh…因此,在上面的shahkalpesh回答中,我们为同一字符串文本指定两个引用并不意味着它们引用堆上的同一字符串?@Jon:if string s=“hello”;字符串t=“ello”;字符串z=“h”+t;s&z是否指向同一个实例?internedf是什么意思?internedf与实习没有直接关系。你说:所有引用类型(实际上,所有类型)的规则都是一样的,不管它们是如何在内部管理的——我想你说的是引用副本,而不是实习。对吗?为什么人们用这种奇怪的方式比较字符串。。。使用String.Compare可以指定区分大小写。在比较之前,这可能比上套管柱更清楚。