列表是按值传递的吗?
Posted
技术标签:
【中文标题】列表是按值传递的吗?【英文标题】:Are ILists passed by value? 【发布时间】:2011-01-20 10:53:57 【问题描述】:除非您在参数上使用 ref 或 out 关键字,否则在 c# 中将 Value Type 参数传递给函数是按值的。但这是否也适用于Reference Types?
具体来说,我有一个接受IList<Foo>
的函数。传递给我的函数的列表是否会是列表的副本及其包含对象的副本?或者对列表的修改也适用于调用者?如果是这样 - 有没有一种聪明的方法可以传递一份副本?
public void SomeFunction()
IList<Foo> list = new List<Foo>();
list.Add(new Foo());
DoSomethingWithCopyOfTheList(list);
..
public void DoSomethingWithCopyOfTheList(IList<Foo> list)
// Do something
【问题讨论】:
感谢大家的快速回复!就像我预期的那样。只是有片刻的不确定性.. 如果你想做一些聪明的事情,你可以创建一个自己的列表类,通过复制隐式转换为 IList。我能看到的唯一好处是,它理论上可以防止您在传递集合时“忘记”制作副本。 不-我不想那样做.. 采用 IEnumerable 的 List 构造函数似乎很聪明。我只需要.. 别怪你。通常,我使用“聪明”作为“不要这样做”的同义词。 【参考方案1】:除非您明确使用ref
或out
,否则所有参数均按值传递。但是,当您传递引用类型的实例时,您按值传递引用。 IE。引用本身被复制,但由于它仍然指向同一个实例,您仍然可以通过此引用修改实例。 IE。不复制实例。参考是。
如果您想复制列表本身,List<T>
有一个 handy constructor,它需要一个 IEnumerable<T>
。
【讨论】:
此外,如果您更改函数主体内的引用,则调用者将看不到此更改。来自我的 +1。 @Aggelos:没错。这是按值传递的属性。【参考方案2】:你并不孤单;这让很多人感到困惑。
这是我喜欢的想法。
变量是一个存储位置。
变量可以存储特定类型的东西。
有两种类型:值类型和引用类型。
引用类型变量的值是对该类型对象的引用。
值类型的变量的值就是该类型的对象。
形参是一种变量。
形式参数分为三种:值参数、引用参数和输出参数。
当您使用变量作为与值形参对应的实参时,该变量的值将被复制到与形参关联的存储中。如果变量是值类型,则制作该值的副本。如果变量是引用类型,则复制引用,两个变量现在引用同一个对象。无论哪种方式,都会制作变量值的副本。
当您将变量用作对应于 out 或 ref 参数的参数时,参数将成为变量的别名。当你说:
void M(ref int x) ...
...
int y = 123;
M(ref y);
你说的是“x 和 y 现在是 同一个变量”。它们都引用相同的存储位置。
我发现这比思考别名的实际实现方式更容易理解——通过将变量的托管地址传递给形参。
清楚吗?
【讨论】:
【参考方案3】:列表是通过引用传递的,所以如果你在 SomeFunction 中修改列表,你也会为调用者修改列表。
您可以通过创建一个新列表来创建列表的副本:
var newList = new List<Foo>(oldList);
【讨论】:
【参考方案4】:您的列表是通过引用传递的。如果您想传递列表的副本,您可以这样做:
IList<Foo> clone = new List<Foo>(list);
如果您在克隆中添加/删除元素,它不会修改列表 但元素本身的修改将在两个列表中被考虑在内。
【讨论】:
+1 解释:...but the modifications of the elements themselves will be taken into account in both lists.
【参考方案5】:
当您按值传递引用类型(不带 ref 或 out 关键字)时,您可以在此方法内修改此引用类型,所有更改都将反映到调用者代码。
要解决您的问题,您可以显式创建一个副本并将此副本传递给您的函数,或者您可以使用:
list.AsReadOnly();
【讨论】:
【参考方案6】:传递引用类型时,您传递引用。这是一个重要的概念。
如果你传递了一个引用
byref,你直接传递 reference(指针)。
byval,你传递了 reference(指针)的副本。
引用不是引用的实例。引用类似于指针。
要传递引用类型实例的副本,您首先必须自己制作副本并传递对副本的引用。因此,您将不会修改原始实例。
【讨论】:
以上是关于列表是按值传递的吗?的主要内容,如果未能解决你的问题,请参考以下文章