class Test
{
static void Func(StringBuilder myString)
{
myString.Append ("test");
myString = null;
}
static void Main()
{
StringBuilder s1 = new StringBuilder();
Func(s1);
Console.WriteLine (s1);
}
}
输出为“Test”,为什么不为null?
如果s1通过引用 传递给Func(),那么为什么myString.Append("test")
会更改它,但myString = null
不会?
提前致谢。
答案 0 :(得分:11)
您按值传递对象的引用。
即。对象的地址按值传递,但对象和对象的地址是相同的。因此,当您调用方法时,VM会复制引用;你只是在改变副本。
在myString.Append
上,您使用复制的引用来获取对象(仍然只有一个对象),然后更改/调用该对象。
你认为你正在做的是:
class Test
{
static void Func(ref StringBuilder myString)
{
myString.Append("test");
myString = null;
}
static void Main(string[] args)
{
StringBuilder s1 = new StringBuilder();
Func(ref s1);
Console.WriteLine(s1);
}
}
答案 1 :(得分:10)
如果通过引用Func()传递s1,那么为什么呢 myString.Append(“test”)确实改变了它
它没有通过引用传递,而是将其地址值传递给函数。
假设S1
指向内存位置0x48,这将传递给Func
,其中Func
参数myString
将开始指向该位置。稍后当您Append
到该位置的文本时,会添加该文本。但是稍后当您将null
分配给myString
时,它会开始指向任何内容,但原始位置保持不变。
您应该看到:Parameter passing in C# by Jon Skeet
请考虑以下图表。
在第1步中,您将创建一个StringBuilder
类型的新对象,并让S1
引用该对象。
在第2步中,将S1
传递给Func
后,现在myString
也指向内存中的同一个对象。
稍后当您Append
通过myString
发送文本时,它会更新原始对象,因为myString
指向对象持有的内存位置。
在步骤3中,当您为myString
分配null时,它会丢失StringBuilder
对象的地址,但这不会更改对象或指针S1
中的任何内容。
答案 2 :(得分:2)
在C#中,默认情况下,复数类型的指针(引用)按值传递。您必须指定它是通过引用传递的,如下所示:
static void Func(ref StringBuilder myString)
{
myString.Append ("test");
myString = null;
}
答案 3 :(得分:0)
将ref
添加到函数中以通过ref。
static void Func(ref StringBuilder myString)
{
myString.Append ("test");
myString = null;
}
然后称之为:
Func(ref s1);
答案 4 :(得分:0)
因为您将StringBuilder s1的引用传递给Func。
在Func中,对同一个StringBuilder实例的引用称为“myString”。
您首先告诉它做某事(“myString.Append("Test")
),然后将引用INSIDE Func设置为null。Append的结果对Main()可见;引用设置为null不会影响Main中的s1。” / p>