C# 通用列表和值引用
我有两个对象,我们把它们叫做C# 通用列表和值引用,c#,C#,我有两个对象,我们把它们叫做A,B和method List<B> DoSomething(ref A a, List<B> b) { List<B> newList = new List<B>(); // //Doing something to ref A // foreach(var elementOfB in b.where(...)) { //
A
,B
和method
List<B> DoSomething(ref A a, List<B> b)
{
List<B> newList = new List<B>();
//
//Doing something to ref A
//
foreach(var elementOfB in b.where(...))
{
//
elementOfB.Name = "...";
//
newList.Add(elementOfB);
}
return newList;
}
实际上,List
是对B元素的引用列表。引用列表已更改,但引用仍然指向相同的对象
如果您需要克隆对象,请查看此图 除了简单类型(int、double等)之外,C#中的所有类型都作为引用传递。如果要创建副本,需要在b.Where(..).ToList时手动执行此操作,然后只创建副本。Where返回IEnumerable,允许使用foreach循环进行迭代
Where(t => IsOk(t));
不创建调用它的IEnumerable
的深度副本。它遍历集合并返回与isOk()条件匹配的项。这意味着它创建了一个新列表,但项目是相同的
若要创建每个项目的副本,应在项目上实现ICloneable
,并将其克隆到新列表中。;我们实际上在做浅层处理:复制对象的引用,而不创建对象的克隆:
// Shallow copy (your actual implementation):
// NewList is not b, but it contains references to objects in b
var NewList = b
.Where(item => ...)
.ToList();
// Deep copy (which probably you're looking for)
// NewList doesn't contain any reference to any objects in b
var NewList = b
.Where(item => ...)
.Select(item => item.Clone()) // You need this, proving that Clone() makes a deep copy
.ToList();
如果要克隆项目,必须为B
类正确实现ICloneable
接口(以确保深度覆盖)
为什么我的列表b改变了它的值
List<B> originalList = ...;
List<B> newList = DoSomething(ref a, originalList);
//now originalList have changed Name field values
因为虽然您分配了一个新列表,但它们现在仍然指向相同的B
实例。在将它们添加到新列表之前,您尚未创建新实例
可以通过复制构造函数克隆现有对象的示例如下:
现在,如果要创建列表,请执行以下操作:
foreach(var elementOfB in b.Where(SomePredicate))
{
elementOfB.Name = "...";
newList.Add(new B(elementOfB));
}
否,其中迭代列表中的元素,不创建副本。您需要手动创建元素的副本为什么要做出这样的假设?OP表示元素的副本而不是列表
iclonable
不能保证任何东西。您可能应该向OP澄清,他仍然需要实现对象的深度复制。ICloneable
的问题是,调用方不知道你在做什么类型的克隆。@Yuval Itzhakov:谢谢,非常想澄清一下。我已经编辑了答案。
foreach(var elementOfB in b.Where(SomePredicate))
{
elementOfB.Name = "...";
newList.Add(new B(elementOfB));
}