通过参考传递只是遗产吗?

Tre*_*ent 7 c# pass-by-reference

也许这对我来说有点天真,但我似乎无法找到/想到"通过引用传递"的体面用例.更改不可变字符串(正如其他一些Q/As所提到的)通常是可以避免的,返回多个变量通常可以通过返回元组,列表,数组等来更好地处理.

在我看来,MSDN上例子很糟糕; 我只是在Square方法中返回一个值,而不是将其声明为void.

在我看来,它似乎是C#的一个遗留部分,而不是它的一个组成部分.有人比我更聪明可以尝试解释为什么它仍然存在和/或一些实际可行的实际用例(即几乎在每种情况下都可以避免更改不可变字符串).

sta*_*ica 6

PS:我跟进了@KallDrexx@newacct的一些评论.我现在看到他们是对的,我错了:我的回答有点误导.优秀的文章"Java是价值传递,该死!" 作者:Scott Stanchfield(特定于Java,但仍然与C#最相关)终于让我信服了.

我将暂时删除我的答案的误导性内容,但可能会在以后删除它们.


通过引用传递不只是使用refout参数.更重要的是,所有引用类型都通过引用传递(因此它们的名称),尽管这是透明的.

以下是三个用于传递引用的常见用例:

  • struct传递它们时防止复制大s.想象一下,你有一个byte[]表示二进制大对象(BLOB)数组,可能是struct包含大量字段的某种类型的大小值的几兆字节.该类型的值可能会占用大量内存.现在您要将此值传递给某个方法.你真的想通过它传递它,即创建一个临时副本吗?

    您可以通过reference 传递大型结构来避免不必要的复制.

    (对我们来说幸运的是,数组如byte[]引用类型,因此数组的内容已经通过refence传递.)

    通常建议(例如在Microsoft的框架设计指南中)具有值类型语义的类型如果超过一定大小(32字节)则应实现为引用类型,因此该用例不应非常频繁.

  • 可变性.如果您希望某个方法能够改变struct传递给它的值,并且您希望调用者观察该对象的版本的变异,那么您需要通过引用(ref)传递.如果值通过值传递给方法,则它会收到一个副本; 改变副本将使原始对象保持不变.

    在上面链接的框架设计指南文章中也提到了这一点.

    请注意针对可变值类型的广泛推荐(参见例如"为什么可变结构是邪恶的?").您应该很少使用refout参数与值类型一起使用.

  • 本回答中提到的COM互操作通常需要您声明refout参数.

  • 这个答案有点误导吗?传递引用类型不会通过引用传递,而是通过引用传递指针值.因此,如果您希望被调用者更改调用者实际引用的对象,您仍然希望使用`ref`关键字. (4认同)