Foreach 更改所有列表

本文关键字:列表 Foreach | 更新日期: 2023-09-27 18:34:19

在List集合上使用foreach时,迭代的对象在集合中明显发生了变化。我希望保留一个集合"副本"供以后使用,但这个"副本"似乎与原始列表集合一起更改。

如何防止我的"副本"集合在循环访问原始列表集合时被更改?

这是我到目前为止尝试过的:

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?
    }
}

Foreach 更改所有列表

如果类型 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.
        }
    }
}

这是因为列表中的对象很可能是引用类型(类)。它与列表完全无关,它与 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

如果您不控制类型并且无法编写复制构造函数,则可以创建一个新对象并复制属性(假设您可以这样做,有时您不能这样做)。