Csharp误区
误区1:"引用类型保存在堆上,值类型保存在栈上"
这个误区主要应归咎于转述这句话的人根本没有动脑筋。第一部分是正确的——引用类型的实例总是在堆上创建的。但第二部分就有问题了。前面讲过,变量的值是在它声明的位置存储的。所以,假定一个类中有一个int类型的实例变量,那么在这个类的任何对象中,该变量的值总是和对象中的其他数据在一起,也就是在堆上。只有局部变量(方法内部声明的变量)和方法参数在栈上。
误区2:"对象在C#中默认是通过引用传递的"
这或许是传播得最广的一个误区了。同样,说这句话的人一般(但并不总是)知道C#实际的行为是什么,但不知道“引用传递”(pass by reference)的真正意思是什么。可惜,那些真正知道引用传递是什么意思的人,在听到这句话时就会被完全搞糊涂。"引用传递"的正式定义相当复杂,要涉及左值(l-values)和类似的计算机科学术语。但最重要的一点是,假如以引用传递的方式来传送一个变量,那么调用的方法可以通过更改其参数值,来改变调用者的变量值。现在请记住,引用类型变量的值是引用,而不是对象本身。不需要按引用来传递参数本身,就可以更改该参数引用的那个对象的内容。例如,下面的方法更改了相关对象StringBuilder的内容,但调用者的表达式引用的仍然是之前的那个对象:
void AppendHello(StringBuilder builder)
{
builder.Append("hello");
}
调用这个方法时,参数值(对StringBuilder的一个引用)是以值传递(pass by value)的方式传递的。如果想在方法内部更改builder变量的值——如执行builder = null;语句,调用者看不见这个改变,刚好跟错误认识相反。
有趣的是,在这种错误说法中,不仅“引用传递”的说法有误,而且“对象传递”的说法也存在问题。无论是引用传递还是值传递,永远不会传递对象本身。涉及一个引用类型时,要么以“引用传递”的方式传递变量,要么以“传值”的方式传递参数值(引用)。最起码,这回答了“当null作为一个传值参数的值来使用时会发生什么”的问题。假如传递的是对象,这时就会出问题,因为没有一个对象可供传递!相反,null引用会采用和其他引用一样的“值传递”的方式传递。

浙公网安备 33010602011771号