在C#中传递引用类型
class Test { static void Func(StringBuilder myString) { myString.Append ("test"); myString = null; } static void Main() { StringBuilder s1 = new StringBuilder(); Func(s1); Console.WriteLine (s1); } }
输出是“测试”,为什么不是空?
如果通过引用 Func()传递s1,那么为什么myString.Append("test")
改变它,但是myString = null
却没有?
提前致谢。
如果通过引用Func()传递s1,那么myString.Append(“test”)为什么会改变它
它不是通过引用传递的,而是将其地址值传递给函数。
假设S1
指向内存位置0x48,这将传递给Func
,其中Func
参数myString
将开始指向该位置。 稍后当您Append
文本Append
到该位置时,会添加该文本。 但是稍后当你为myString
分配null
时,它开始指向什么,但原始位置保持不变。
您应该看到: Jon Skeet在C#中传递参数
请考虑以下图表。 在第1步中,您将创建一个StringBuilder
类型的新对象,并让S1
引用该对象。
在步骤2中,在将S1
传递给Func
,现在myString
也指向内存中的同一对象。
稍后当你Append
,通过myString
短信时,它会更新原始对象,因为myString
指向对象持有的内存位置。
在步骤3中,当您为myString
分配null时,它会丢失StringBuilder
对象的地址,但这不会更改对象或指针S1
中的任何内容。
您是按值传递对象的引用。
即对象的地址按值传递,但对象和对象的地址是相同的。 因此,当您调用方法时,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); } }
更长的解释: http : //javadude.com/articles/passbyvalue.htm
在C#中,默认情况下,复数类型的指针(引用)按值传递。 您必须指定它是通过引用传递的,如下所示:
static void Func(ref StringBuilder myString) { myString.Append ("test"); myString = null; }
将ref
添加到函数以通过ref传递它。
static void Func(ref StringBuilder myString) { myString.Append ("test"); myString = null; }
然后称之为:
Func(ref s1);
因为您将StringBuilder s1的引用传递给Func。 在Func中,对同一个StringBuilder实例的引用称为“myString”。 首先告诉它做某事(“ myString.Append("Test")
),然后将引用INSIDE Func设置为null。Append的结果对Main()可见;引用设置为null不会影响s1 in主要。