询问者
这是值参数传递还是引用参数传递

常规讨论
-
自己定义一个类MyClass.
调用方法 MyMethod(MyClass instance)时 参数是通过值传递还是通过引用传递的?
看了 C#3.0 语言规范说 除了加 ref、out 以外的参数传递都是传值,是这样吗?(5.14/5.15)
谢谢!
Forrest- 已更改类型 Forrest Guo 2010年3月11日 3:03
全部回复
-
关于值类型和引用类型的讨论一直没能停止。我面试的时候也经常问他们这些问题。可惜,很少有人答得对。
以上大家的解释完全合理。但问题是,按值传递的对象根据其类型不同,有不同的表现形式。
例如,默认情况下的值传递,对于值类型来讲,其本身的数据结构会被克隆后传递,而对于引用类型来讲,引用类型的地址标示符 (这里我不说在托管堆上的地址) 被克隆然后被传递,由于其地址标识符能被用来定位该对象的实例,则任何对此对象的更改都会立即被生效。
但有一个特殊,那就是 string。string 是引用类型,但它却表现为值类型。
另外,所有的 struct 是值类型,所有的 class 是引用类型。还有,值类型不一定就一定存储在栈上,引用类型则会被存储在堆上。详细请参考 Dixin Yan 的 Blog:理解 C# 中的值类型和引用类型。
Mark Zhou -
简单的说,可以设置成null的就是引用类型,不能的就是值类型(string除外)。
同时,函数返回值也可是这个规律,引用类型的返回值也是引用,修改也有效(也是string除外)。
霸王
这个说法也不完全正确。例如 int? intValue = null; 而 intValue 是值类型的。详细请参考我的 Blog Why can assign “null” to nullable types。
Mark Zhou -
或者说,MyMethod(MyClass instance) 这里的instance 本身就是一个“引用的值”,类似c++的指针,因此这里传的是值进去,也就是instance 的引用,对instance的操作是会反映出来的
MyMethod(ref MyClass instance) 这样的话就是instance 的引用,也就是“引用的值的引用”,类似c++里指针的指针,instance 的引用值会被改变(原来的对象被销毁[如果没别的引用的话],新建了一个对象,并把这个对象的引用值给了这个 instance变量,真绕口)
霸王
我同样从 c++转C#,对这个思维很有亲切感 呵呵 -
大家需要在适当的时候转变思维方式,特别是当大家接触到一些新技术新理念时。这也就是程序员的“先进性”体现。
我数十年前是搞 VB 的,VB 里面的默认传值方式就是值传递 (ByVal),现在玩 C#,很多东西就不使用了,比如,VB 中的 Object 支持晚期绑定,但 C# 却不支持,有时候我也会茫然为什么 C# 会没有类似 RaiseEvent 语句。每种语言都有语言的优势和特点,我个人不喜欢拿几种语言在一起比较,因为没有意义。
一种新技术的出现,大家要先思考为什么需要它,然后再考虑如何使用它。否则,如果是为了使用它而接触它,就会产生一知半解。这也是我给大家学习 C# 的一种提示。比如,如果您知道 COM 互操作,您就一定知道为什么 C# 4.0 要引入可选参数,您也就知道什么时候该用重载,而什么时候该用可选参数了。其实很多问题也就迎刃而解了。
希望此贴对大家有帮助。
Mark Zhou