通过副本或参考传递?
Posted
技术标签:
【中文标题】通过副本或参考传递?【英文标题】:Pass by copy or reference? 【发布时间】:2011-04-03 01:24:02 【问题描述】:我对 C# 有点陌生,只是想知道是否有一个默认作为副本传递的类列表(常用)。如何识别它们?
我知道基本的基本对象类型——int、uint、float、strings……——是通过复制传递的。
【问题讨论】:
Thomas Levesque 的回答回答了这个问题。需要注意的是,当值类型被复制时,默认情况下它只是一个浅拷贝——如果一个结构包含一个引用类型,则该副本将指向同一个引用对象,而不是克隆一个新对象。 【参考方案1】:在 C# / .Net 中,对象可以分为值类型或引用类型 [1]。值类型是派生自System.ValueType
并在C# 中使用struct
类型声明定义的任何类型。这些是通过副本/值传递的。
引用类型不是从System.ValueType
派生的类型,而是在C# 中使用class
关键字定义的。引用类型实例的标识符称为引用(类似于指针)。默认情况下,这些也是按值传递的,但仅传递引用而不传递整个对象。
您的问题还提到 string
实例是通过副本传递的。 .Net 中的String
是一个引用类型(直接派生自System.Object
),因此不通过完整副本传递。
[1] 指针在这里可能值得他们自己的类,但我在本次讨论中忽略了它们。
【讨论】:
谢谢,System.ValueType 之间的继承帮助我理解了这一点!【参考方案2】:默认情况下,所有类型都按值传递。 值类型 (struct
) 和引用类型 (class
) 之间的区别在于,对于值类型,值的副本是传递给方法,而对于引用类型,只传递一个引用。
See MSDN 了解更多详情。
另外,不要混淆值/引用类型的概念,以及按值或按引用传递参数的概念。详情请参阅 Jon Skeet 的 this article
【讨论】:
不,两者都是按值传递的。在引用的情况下,虽然它是按值传递的引用,而不是对象。 确实,措辞很糟糕……我修好了【参考方案3】:一般来说,
值类型,其中包括本机类型(int
、float
、...)以及 struct
s 是“按副本”传递的(如您所说它),而在
引用类型,其中包括class
es,只复制一个引用而不是完整的对象。
但请注意,string 不是“通过复制”传递的!这是一个引用类型,但由于它是不可变的,it behaves similar to a value type。
请注意,ref
关键字在两种情况下都很有用:对于值类型,这意味着将值复制回来。在引用类型的情况下,这意味着 reference 可以更改(即,您可以将变量分配给新对象,而不仅仅是更改对象的属性。)
【讨论】:
-1 所有类型在 c# 中都是按值传递的,除非您使用 ref 或 out 关键字。碰巧的是,对于引用类型,值就是引用。例如如果您将引用类型传递给方法并在方法中将其设置为 null,如果不将您传递的变量清空,则仅在方法中传递 COPY。 @Ben:没错,这就是为什么我在第二种情况下避免使用“通过引用”这个短语,并明确提到了 ref 关键字的使用。我已经改写了我的答案以使这一点更清楚。 删除了我的 -1 因为你更新了你的答案更清楚了。 @Ben:谢谢(删除 -1 以及反馈)。【参考方案4】:还要注意结构对象可以包含引用类型:
struct Currency
int Amount get;set; // is referenced by value (copy)
string Code get;set; // is referenced by reference
当您像这样使用该结构时:
var obj1 = new CurrencyAmount = 1, Code = "USD";
var obj2 = obj1;
然后
object.ReferenceEquals(obj1.Code, obj2.Code); // false - string is reference type, but used inside value type
如果您已将 Currency 声明为类,则对 Code 的引用是相同的。
【讨论】:
以上是关于通过副本或参考传递?的主要内容,如果未能解决你的问题,请参考以下文章
传递常量引用与创建临时常量副本相同,那么为啥要传递常量引用呢? [复制]