如何在 C# 中克隆通用列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/222598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:47:20  来源:igfitidea点击:

How do I clone a generic list in C#?

c#genericslistclone

提问by Fiona

I have a generic list of objects in C#, and wish to clone the list. The items within the list are cloneable, but there doesn't seem to be an option to do list.Clone().

我在 C# 中有一个通用的对象列表,并希望克隆该列表。列表中的项目是可克隆的,但似乎没有选项 do list.Clone()

Is there an easy way around this?

有没有简单的方法来解决这个问题?

采纳答案by ajm

You can use an extension method.

您可以使用扩展方法。

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}

回答by Anthony Potts

For a shallow copy, you can instead use the GetRange method of the generic List class.

对于浅拷贝,您可以改用泛型 List 类的 GetRange 方法。

List<int> oldList = new List<int>( );
// Populate oldList...

List<int> newList = oldList.GetRange(0, oldList.Count);

Quoted from: Generics Recipes

引自:泛型食谱

回答by Jeff Yates

If your elements are value types, then you can just do:

如果您的元素是值类型,那么您可以这样做:

List<YourType> newList = new List<YourType>(oldList);

However, if they are reference types and you want a deep copy (assuming your elements properly implement ICloneable), you could do something like this:

但是,如果它们是引用类型并且您想要深层复制(假设您的元素正确实现ICloneable),则可以执行以下操作:

List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

Obviously, replace ICloneablein the above generics and cast with whatever your element type is that implements ICloneable.

显然,替换ICloneable上面的泛型并使用实现ICloneable.

If your element type doesn't support ICloneablebut does have a copy-constructor, you could do this instead:

如果您的元素类型不支持ICloneable但确实有一个复制构造函数,您可以这样做:

List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

Personally, I would avoid ICloneablebecause of the need to guarantee a deep copy of all members. Instead, I'd suggest the copy-constructor or a factory method like YourType.CopyFrom(YourType itemToCopy)that returns a new instance of YourType.

就个人而言,我会避免,ICloneable因为需要保证所有成员的深层副本。相反,我建议使用复制构造函数或类似的工厂方法YourType.CopyFrom(YourType itemToCopy)返回YourType.

Any of these options could be wrapped by a method (extension or otherwise).

这些选项中的任何一个都可以由方法(扩展或其他)包装。

回答by James Curran

If you only care about value types...

如果您只关心值类型...

And you know the type:

你知道类型:

List<int> newList = new List<int>(oldList);

If you don't know the type before, you'll need a helper function:

如果您之前不知道类型,则需要一个辅助函数:

List<T> Clone<T>(IEnumerable<T> oldList)
{
    return newList = new List<T>(oldList);
}

The just:

刚刚:

List<string> myNewList = Clone(myOldList);

回答by Patrick Desjardins

public static object DeepClone(object obj) 
{
  object objResult = null;
  using (MemoryStream  ms = new MemoryStream())
  {
    BinaryFormatter  bf =   new BinaryFormatter();
    bf.Serialize(ms, obj);

    ms.Position = 0;
    objResult = bf.Deserialize(ms);
  }
  return objResult;
}

This is one way to do it with C# and .NET 2.0. Your object requires to be [Serializable()]. The goal is to lose all references and build new ones.

这是使用 C# 和 .NET 2.0 实现的一种方法。您的对象需要是[Serializable()]. 目标是丢失所有引用并构建新引用。

回答by pratik

public static Object CloneType(Object objtype)
{
    Object lstfinal = new Object();

    using (MemoryStream memStream = new MemoryStream())
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
        binaryFormatter.Serialize(memStream, objtype); memStream.Seek(0, SeekOrigin.Begin);
        lstfinal = binaryFormatter.Deserialize(memStream);
    }

    return lstfinal;
}

回答by Ajith

After a slight modification you can also clone:

稍作修改后,您还可以克隆:

public static T DeepClone<T>(T obj)
{
    T objResult;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
        ms.Position = 0;
        objResult = (T)bf.Deserialize(ms);
    }
    return objResult;
}

回答by Peter

public class CloneableList<T> : List<T>, ICloneable where T : ICloneable
{
  public object Clone()
  {
    var clone = new List<T>();
    ForEach(item => clone.Add((T)item.Clone()));
    return clone;
  }
}

回答by Derek Liang

Use AutoMapper (or whatever mapping lib you prefer) to clone is simple and a lot maintainable.

使用 AutoMapper(或您喜欢的任何映射库)进行克隆非常简单且易于维护。

Define your mapping:

定义您的映射:

Mapper.CreateMap<YourType, YourType>();

Do the magic:

施展魔法:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);

回答by Furkan Kat?

You can use extension method:

您可以使用扩展方法:

namespace extension
{
    public class ext
    {
        public static List<double> clone(this List<double> t)
        {
            List<double> kop = new List<double>();
            int x;
            for (x = 0; x < t.Count; x++)
            {
                kop.Add(t[x]);
            }
            return kop;
        }
   };

}

You can clone all objects by using their value type members for example, consider this class:

例如,您可以使用它们的值类型成员克隆所有对象,考虑这个类:

public class matrix
{
    public List<List<double>> mat;
    public int rows,cols;
    public matrix clone()
    { 
        // create new object
        matrix copy = new matrix();
        // firstly I can directly copy rows and cols because they are value types
        copy.rows = this.rows;  
        copy.cols = this.cols;
        // but now I can no t directly copy mat because it is not value type so
        int x;
        // I assume I have clone method for List<double>
        for(x=0;x<this.mat.count;x++)
        {
            copy.mat.Add(this.mat[x].clone());
        }
        // then mat is cloned
        return copy; // and copy of original is returned 
    }
};

Note: if you do any change on copy (or clone) it will not affect the original object.

注意:如果您对复制(或克隆)进行任何更改,它不会影响原始对象。