none
这是值参数传递还是引用参数传递 RRS feed

  • 常规讨论

  • 自己定义一个类MyClass.
    调用方法 MyMethod(MyClass instance)时  参数是通过值传递还是通过引用传递的? 

    看了 C#3.0 语言规范说 除了加 ref、out 以外的参数传递都是传值,是这样吗?(5.14/5.15)

    谢谢!
    Forrest
    2010年3月10日 7:43

全部回复

  • 类的话应该是传引用,否则 DataAdapter.Fill(DataSet ds) 就变成搞笑了。

    不过为了彻底抛弃这个烦恼,我都用接口当参数了,接口实现一个GetInstance() 返回一个实例的引用,可以保证操作的正确性。还可以实现其他功能,扩展性也好。

    霸王
    2010年3月10日 7:54
  • 或者说,MyMethod(MyClass instance) 这里的instance 本身就是一个“引用的值”,类似c++的指针,因此这里传的是值进去,也就是instance 的引用,对instance的操作是会反映出来的

    MyMethod(ref MyClass instance) 这样的话就是instance 的引用,也就是“引用的值的引用”,类似c++里指针的指针,instance 的引用值会被改变(原来的对象被销毁[如果没别的引用的话],新建了一个对象,并把这个对象的引用值给了这个 instance变量,真绕口)

    霸王
    2010年3月10日 7:59
  • 你好!
         可能文档中的说法令你产生了误解,我详细解释一下:
         的确在默认情况下,方法的参数都是按值传递的,引用类型的变量中保存的是对象在托管堆中的地址,这个地址本身是按值传递的,这就是文档中想表达的意思,事实也的确如此!
         但是引用类型的参数起到的效果是你理解的那种按引用传递,因为形参和实参中保存的是同样的地址(按值传递复制来的),所以在形参上做修改会影响实参的!
         当然,以上讨论是在没有使用ref,out关键字的情况下做的!
         希望对你有帮助!
         如果还有不清楚的地方,我们可以继续交流啊!
    周雪峰
    2010年3月10日 8:04
    版主
  • MyMethod(MyClass instance) instance 是传值,没错。

    但是你要知道instance 是怎么来的。一般来说调用MyMethod 方法,你要执行下面两行代码:
    MyClass arg = new MyClass();
    MyMethod(arg);

    此时 arg 保存着托管堆中的MyClass 对象的地址。 而传值指的是arg 和instance 之间,就是把arg 保存的地址值拷贝到instance 里面。这样instance 也就指向了MyClass 对像。 所以,不矛盾。
    2010年3月10日 8:15
  • 关于值类型和引用类型的讨论一直没能停止。我面试的时候也经常问他们这些问题。可惜,很少有人答得对。

    以上大家的解释完全合理。但问题是,按值传递的对象根据其类型不同,有不同的表现形式。

    例如,默认情况下的值传递,对于值类型来讲,其本身的数据结构会被克隆后传递,而对于引用类型来讲,引用类型的地址标示符 (这里我不说在托管堆上的地址) 被克隆然后被传递,由于其地址标识符能被用来定位该对象的实例,则任何对此对象的更改都会立即被生效。

    但有一个特殊,那就是 string。string 是引用类型,但它却表现为值类型。

    另外,所有的 struct 是值类型,所有的 class 是引用类型。还有,值类型不一定就一定存储在栈上,引用类型则会被存储在堆上。详细请参考 Dixin Yan 的 Blog:理解 C# 中的值类型和引用类型
    Mark Zhou
    2010年3月10日 9:29
  • 简单的说,可以设置成null的就是引用类型,不能的就是值类型(string除外)。

    同时,函数返回值也可是这个规律,引用类型的返回值也是引用,修改也有效(也是string除外)。

    霸王
    2010年3月10日 9:38
  • 简单的说,可以设置成null的就是引用类型,不能的就是值类型(string除外)。

    同时,函数返回值也可是这个规律,引用类型的返回值也是引用,修改也有效(也是string除外)。

    霸王

    这个说法也不完全正确。例如 int? intValue = null; 而 intValue 是值类型的。详细请参考我的 Blog Why can assign “null” to nullable types
    Mark Zhou
    2010年3月10日 9:57
  • int? intValue = null;

    这写法还真没见过,不知道啥意思……汗……
    霸王
    2010年3月10日 10:04
  • int? intValue = null;

    这写法还真没见过,不知道啥意思……汗……
    霸王

    这个是可空类型,从.NET Framework 2.0开始引入,你可以参考一下文档!
    周雪峰
    2010年3月10日 10:16
    版主
  • 可空类型,顾名思义哈。

    也许会有些地方有用,不过我只拿c#当c++的替代品罢了,c++的托管代码实在是太难看了,指针也被半喀嚓,就改用c#了。
    霸王
    2010年3月10日 12:22
  • 我很喜欢这样的讨论^_^
    2010年3月10日 12:54
  • 我也很喜欢这样的讨论!希望大家多做这样的讨论啊!
    周雪峰
    2010年3月10日 13:51
    版主
  • 有些帖子是斑竹结帖太快吧,打了勾的一般很少有人看有人回。。。

    霸王
    2010年3月10日 14:05
  • 实际上只有超过很长时间提问者都没有标记的帖子,版主才会标记的!如果你认为版主的标记过快,或是并不是你想要的答案,可以在“版务交流”这个版块反应这个问题啊!

    周雪峰
    2010年3月10日 14:29
    版主
  • 其实很多问题都有可扩展性,或者还有更好的解决方法,结与不结确实都比较难办。

    是否可以考虑把一些具有通性的问题结了之后把类别改成“讨论”,再适当改一下标题,针对论坛的自动搜索优化一下,也许能稍微好点。


    霸王
    2010年3月10日 14:40
  • 你好!
         挺好的建议,但是我认为在原贴上修改不是很合适,我们可以另开新的讨论帖来重新讨论啊!
    周雪峰
    2010年3月11日 2:17
    版主
  • 或者说,MyMethod(MyClass instance) 这里的instance 本身就是一个“引用的值”,类似c++的指针,因此这里传的是值进去,也就是instance 的引用,对instance的操作是会反映出来的

    MyMethod(ref MyClass instance) 这样的话就是instance 的引用,也就是“引用的值的引用”,类似c++里指针的指针,instance 的引用值会被改变(原来的对象被销毁[如果没别的引用的话],新建了一个对象,并把这个对象的引用值给了这个 instance变量,真绕口)

    霸王

    我同样从 c++转C#,对这个思维很有亲切感 呵呵
    2010年3月11日 3:11
  • 我过去也是C++程序员,不过已经是很久的事情了啊!看到各位C++的同行了,感触很多,真是令人怀念的日子啊!
    除了语法和C++类似,当然还有名字类似,C#和C++的差别很大,从底层开始差别就很大,过去的思维和技巧多数都不再适用了!
    周雪峰
    2010年3月11日 7:20
    版主
  • 大家需要在适当的时候转变思维方式,特别是当大家接触到一些新技术新理念时。这也就是程序员的“先进性”体现。

    我数十年前是搞 VB 的,VB 里面的默认传值方式就是值传递 (ByVal),现在玩 C#,很多东西就不使用了,比如,VB 中的 Object 支持晚期绑定,但 C# 却不支持,有时候我也会茫然为什么 C# 会没有类似 RaiseEvent 语句。每种语言都有语言的优势和特点,我个人不喜欢拿几种语言在一起比较,因为没有意义。

    一种新技术的出现,大家要先思考为什么需要它,然后再考虑如何使用它。否则,如果是为了使用它而接触它,就会产生一知半解。这也是我给大家学习 C# 的一种提示。比如,如果您知道 COM 互操作,您就一定知道为什么 C# 4.0 要引入可选参数,您也就知道什么时候该用重载,而什么时候该用可选参数了。其实很多问题也就迎刃而解了。

    希望此贴对大家有帮助。


    Mark Zhou
    2010年3月11日 9:08
  • 最爱c++(其实是c)里的分配内存,一开始分配一块大的,所有操作都放里面了(除了栈上的临时变量),可以为所欲为,还可以实现即时存储,哈哈

    至于帖子的标题问题,其实关键还是设法优化查询系统吧,虽然有填tag,但一般都填不太精确,全文搜又很不经济,这个也是论坛永恒的问题。

    霸王
    2010年3月11日 14:32
  • string就是引用类型,不会“表现为”值类型,但一个string实例是不可变的,所以直接传递一个string给方法不可能使这个string的值改变。
    2013年1月5日 10:29
  • 你好! string本身是引用类型,但是是很特殊的引用类型,微软尽量让string的行为看上去像值类型。当你修改一个string的时候,实际上会自动创建一个新的string

    周雪峰

    2013年1月7日 2:48
    版主