在List集合上使用foreach时,迭代对象在集合中显然会发生变化。我希望保留一个集合" copy"供以后使用,但这个" copy"似乎与原始列表集合一起被更改。
我如何保留我的"复制"循环遍历原始列表集合时是否更改了集合?
这是我迄今为止所尝试过的:
private List<T> _listCopy;
public Constructor(List<T> inputList)
{
_listCopy = new List<T>(inputList);
foreach(var obj in inputList) {
// This changes both inputList and _listCopy.
// How can i keep _listCopy, from being edited as well?
}
}
答案 0 :(得分:2)
如果类型T是引用类型,则数组副本是列表结构的副本,但不是列表项的副本!复制的列表仍包含对原始项目的引用!如果要更改列表中的对象并保持原始对象不变,则还必须克隆对象!
您可以使用此接口定义将克隆方法添加到此类:
public interface IShallowClonable<T>
{
T ShallowClone();
}
public MyClass : IShallowClonable<MyClass>
{
//TODO: define class members.
public T ShallowClone()
{
return (T)MemberwiseClone(this);
}
}
像这样使用
class Test<T> where T : IShallowClonable<T>
{
private List<T> _listCopy;
public Constructor(List<T> inputList)
{
_listCopy = new List<T>(inputList.Count);
foreach(T obj in inputList) {
_listCopy.Add(obj.ShallowClone());
}
}
private void MakeChangesInListCopy()
{
foreach(T obj in _listCopy) {
obj.ApplyChange((); // You'll need T to implement another interface or
// to inherit from another class for this to work.
}
}
}
答案 1 :(得分:1)
这是因为列表中的对象很可能是引用类型(类)。它与列表无关,它与C#中引用类型的行为方式有关。如果要复制对象,则应创建新对象并复制相应的状态。如果您自己编写类,最好的方法是创建一个复制构造函数。
class SomeType
{
public string SomeState { get; set; }
public SomeType()
{
}
public SomeType(SomeType original)
{
this.SomeState = original.SomeState;
}
}
然后您可以通过各种方式复制列表。例如,使用LINQ
List<SomeType> copyList = originalList.Select(o => new SomeType(o)).ToList();
更重要的是,您应该了解在使用引用类型时,分配不会复制对象。对于该类型的每种用法都是如此。例如变量
SomeType a = new SomeType { SomeState = "1" };
SomeType b = a;
b.SomeState = "2";
Console.WriteLine(a.SomeState); //prints "2" because both variables refer to the same object
如果你不控制类型并且不能编写复制构造函数,你可以创建一个新对象并复制属性(假设你可以这样做,有时候你不能)。