c# 中是不是默认通过引用传递数组或列表?
Posted
技术标签:
【中文标题】c# 中是不是默认通过引用传递数组或列表?【英文标题】:Are arrays or lists passed by default by reference in c#?c# 中是否默认通过引用传递数组或列表? 【发布时间】:2010-11-01 07:55:58 【问题描述】:有吗?或者为了加快我的程序,我应该通过引用传递它们吗?
【问题讨论】:
为了加快你的程序,你应该 (1) 设定有意义的目标,(2) 测试你是否达到了你的目标,(3) 如果你没有,使用分析工具来找到最慢的东西,然后 (4) 优化最慢的东西。 另见***.com/q/4311226/344822 @EricLippert 您的评论比任何已发布的答案都更好地回答了 OP 的真正问题。每个人都被“按值传递引用”技术分心,以至于他们完全忽略了关于性能优化的真正问题。不幸的是,OP 传达他的需求相当糟糕,其他答案至少会帮助谷歌人群。 “其他答案至少会帮助谷歌人群”——他们会的! :) 【参考方案1】:引用按值传递。
.NET 中的数组是堆上的对象,所以你有一个参考。该引用是按值传递的,这意味着调用者将看到对数组内容的更改,但重新分配数组不会:
void Foo(int[] data)
data[0] = 1; // caller sees this
void Bar(int[] data)
data = new int[20]; // but not this
如果您添加 ref
修饰符,则 reference 将通过 引用 传递 - 调用者将看到上述任一更改。
【讨论】:
答案是正确的,但我非常讨厌那些声明“引用按值传递”的人。它混淆了这个问题。是的,引用(内存地址)是按值传递的,但这不是问题。 @WernerVA 我很感兴趣你认为你会如何以不同的方式表达它仍然是正确和明确 我不会表达不同,只是可能更详细一点。 这不能回答问题的速度部分。您可能很明显,与发生的数百个其他更昂贵的操作相比,优化参考副本将完全可以忽略不计,但 OP 确实特别提出了这个问题。 @Dan 速度部分本质上与“如果数组按值传递 - 意味着数组内容的副本 - 这意味着分配和所有内存的副本”。由于传递的是 reference,因此没有要回答的性能问题 - 问题的这一部分被渲染为没有实际意义并自动回答。除了现在它还在 cmets 中明确回答...【参考方案2】:它们是按值传递的(所有既不是 ref 也不是 out 的参数也是如此),但值 是对对象的引用,因此它们实际上是通过引用传递的。
【讨论】:
【参考方案3】:是的,它们在 C# 中默认通过引用传递。 C# 中的所有对象都是,但值类型除外。更准确地说,它们是“按值引用”传递的;也就是说,您在方法中看到的变量的值是对传递的原始对象的引用。这是一个小的语义点,但有时可能很重要。
【讨论】:
引用按值传递;这与“它们通过引用传递”非常不同。 这与事实完全相反。引用this post from John Skeet:“默认情况下,在 C# 中,所有参数都是按值传递的。仅当显式包含 out 或 ref 修饰符时,参数才会通过引用传递。但是,您需要注意,当参数的类型是引用类型,您传递的是引用而不是实际对象”。它只是按值传递的引用(内存地址)。【参考方案4】:(1) 没有人明确回答 OP 的问题,所以这里是:
没有。将数组或列表作为引用显式传递不会影响性能。 避免了 OP 担心可能发生的事情,因为该函数已经在引用(按值传递)上运行。最佳答案很好地解释了这意味着什么,提供了宜家回答原始问题的方式。(2) 给大家的好建议:
阅读 Eric Lippert 关于何时/如何进行优化的建议。过早的优化是万恶之源。(3) 重要的,尚未提及的:
需要通过引用传递任何内容(值或引用)的用例很少见。 这样做为您提供了额外的方法来让自己在脚下开枪,这就是 C# 让您在方法调用中也使用“ref”关键字的原因。较旧的(Java 之前的)语言仅让您在方法声明中指示传递引用。这带来了无穷无尽的问题。 Java 吹嘘它根本不允许你这样做。【讨论】:
以上是关于c# 中是不是默认通过引用传递数组或列表?的主要内容,如果未能解决你的问题,请参考以下文章
Swift 是不是有类似“ref”关键字的东西强制参数通过引用传递?