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

发布于 2025-01-18 04:19:38 字数 97 浏览 5 评论 0原文

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

有一个简单的方法吗?

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().

Is there an easy way around this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

凉薄对峙 2025-01-25 04:19:39

无需将类作为可序列化的标记,在我们的测试中,使用newtonsoft jsonserialializer甚至比使用二进制构造者更快。使用每个对象上可用的扩展方法。

注意:私人成员不是克隆的

标准.NET JavaScriptSerializer选项:

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

使用 newtonsoft json

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}

There is no need to flag classes as Serializable and in our tests using the Newtonsoft JsonSerializer even faster than using BinaryFormatter. With extension methods usable on every object.

attention: private members are not cloned

Standard .NET JavascriptSerializer option:

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

Faster option using Newtonsoft JSON:

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}
夜未央樱花落 2025-01-25 04:19:39
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();
記憶穿過時間隧道 2025-01-25 04:19:39
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;
}
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;
}
胡渣熟男 2025-01-25 04:19:39
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;
  }
}
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;
  }
}
白色秋天 2025-01-25 04:19:39
    public List<TEntity> Clone<TEntity>(List<TEntity> o1List) where TEntity : class , new()
    {
        List<TEntity> retList = new List<TEntity>();
        try
        {
            Type sourceType = typeof(TEntity);
            foreach(var o1 in o1List)
            {
                TEntity o2 = new TEntity();
                foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
                {
                    var val = propInfo.GetValue(o1, null);
                    propInfo.SetValue(o2, val);
                }
                retList.Add(o2);
            }
            return retList;
        }
        catch
        {
            return retList;
        }
    }
    public List<TEntity> Clone<TEntity>(List<TEntity> o1List) where TEntity : class , new()
    {
        List<TEntity> retList = new List<TEntity>();
        try
        {
            Type sourceType = typeof(TEntity);
            foreach(var o1 in o1List)
            {
                TEntity o2 = new TEntity();
                foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
                {
                    var val = propInfo.GetValue(o1, null);
                    propInfo.SetValue(o2, val);
                }
                retList.Add(o2);
            }
            return retList;
        }
        catch
        {
            return retList;
        }
    }
那片花海 2025-01-25 04:19:39

如果您需要具有相同容量的克隆列表,则可以尝试以下操作:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}

If you need a cloned list with the same capacity, you can try this:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}
苍风燃霜 2025-01-25 04:19:39

您可以使用扩展方法:

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

}

您可以通过使用其值类型成员来克隆所有对象,例如,考虑此类:

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

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

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.

桃扇骨 2025-01-25 04:19:39

在这种情况下,使用铸件可能会有所帮助,以备浅副本:

IList CloneList(IList list)
{
    IList result;
    result = (IList)Activator.CreateInstance(list.GetType());
    foreach (object item in list) result.Add(item);
    return result;
}

应用于通用列表:

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);

Using a cast may be helpful, in this case, for a shallow copy:

IList CloneList(IList list)
{
    IList result;
    result = (IList)Activator.CreateInstance(list.GetType());
    foreach (object item in list) result.Add(item);
    return result;
}

applied to generic list:

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);
随波逐流 2025-01-25 04:19:39

如果我需要集合的深层复制,我有最喜欢的方法,如下所示:

public static IEnumerable<T> DeepCopy<T>(this IEnumerable<T> collectionToDeepCopy)
{
    var serializedCollection = JsonConvert.SerializeObject(collectionToDeepCopy);
    return JsonConvert.DeserializeObject<IEnumerable<T>>(serializedCollection);
}

If I need deep copy of collection, I have favorite approach like this:

public static IEnumerable<T> DeepCopy<T>(this IEnumerable<T> collectionToDeepCopy)
{
    var serializedCollection = JsonConvert.SerializeObject(collectionToDeepCopy);
    return JsonConvert.DeserializeObject<IEnumerable<T>>(serializedCollection);
}
杀手六號 2025-01-25 04:19:39

我使用自动应用程序复制对象。我只是设置了将一个对象映射到自身的映射。您可以以任何方式包装此操作。

http://automapper.codeplex.com/

I use automapper to copy an object. I just setup a mapping that maps one object to itself. You can wrap this operation any way you like.

http://automapper.codeplex.com/

疯到世界奔溃 2025-01-25 04:19:39

您可以使用 List.ConvertAll(Converter) 方法创建一个包含原始列表所有元素的新列表,并使用返回输入值的转换函数。

List<int> originalList = new List<int> { 1, 2, 3, 4, 5 };
List<int> clonedList = new List<int>(originalList.ConvertAll(x => x));

You can use the List<T>.ConvertAll(Converter<T, T>) method to create a new list containing all the elements of the original list, and use a conversion function that returns the input value.

List<int> originalList = new List<int> { 1, 2, 3, 4, 5 };
List<int> clonedList = new List<int>(originalList.ConvertAll(x => x));
红玫瑰 2025-01-25 04:19:39

我已经为自己的一些扩展而制作了,可以转换不实现iClonable的项目的偶像

static class CollectionExtensions
{
    public static ICollection<T> Clone<T>(this ICollection<T> listToClone)
    {
        var array = new T[listToClone.Count];
        listToClone.CopyTo(array,0);
        return array.ToList();
    }
}

I've made for my own some extension which converts ICollection of items that not implement IClonable

static class CollectionExtensions
{
    public static ICollection<T> Clone<T>(this ICollection<T> listToClone)
    {
        var array = new T[listToClone.Count];
        listToClone.CopyTo(array,0);
        return array.ToList();
    }
}
送君千里 2025-01-25 04:19:39

您也可以简单地使用toarray将列表转换为数组,然后使用array.clone.clone(...)克隆数组。
根据您的需求,阵列类中包含的方法可以满足您的需求。

You could also simply convert the list to an array using ToArray, and then clone the array using Array.Clone(...).
Depending on your needs, the methods included in the Array class could meet your needs.

满身野味 2025-01-25 04:19:39

以下代码应以最小的更改转移到列表中。

基本上,它的工作原理是在每个连续循环中插入更大范围的新随机数。如果已经存在与它相同或更高的数字,请将这些随机数上移一位,以便它们转移到新的更大范围的随机索引中。

// Example Usage
int[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);

for(int i = 0; i < toSet.Length; i++)
    toSet[i] = selectFrom[indexes[i]];


private int[] getRandomUniqueIndexArray(int length, int count)
{
    if(count > length || count < 1 || length < 1)
        return new int[0];

    int[] toReturn = new int[count];
    if(count == length)
    {
        for(int i = 0; i < toReturn.Length; i++) toReturn[i] = i;
        return toReturn;
    }

    Random r = new Random();
    int startPos = count - 1;
    for(int i = startPos; i >= 0; i--)
    {
        int index = r.Next(length - i);
        for(int j = startPos; j > i; j--)
            if(toReturn[j] >= index)
                toReturn[j]++;
        toReturn[i] = index;
    }

    return toReturn;
}

The following code should transfer onto a list with minimal changes.

Basically it works by inserting a new random number from a greater range with each successive loop. If there exist numbers already that are the same or higher than it, shift those random numbers up one so they transfer into the new larger range of random indexes.

// Example Usage
int[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);

for(int i = 0; i < toSet.Length; i++)
    toSet[i] = selectFrom[indexes[i]];


private int[] getRandomUniqueIndexArray(int length, int count)
{
    if(count > length || count < 1 || length < 1)
        return new int[0];

    int[] toReturn = new int[count];
    if(count == length)
    {
        for(int i = 0; i < toReturn.Length; i++) toReturn[i] = i;
        return toReturn;
    }

    Random r = new Random();
    int startPos = count - 1;
    for(int i = startPos; i >= 0; i--)
    {
        int index = r.Next(length - i);
        for(int j = startPos; j > i; j--)
            if(toReturn[j] >= index)
                toReturn[j]++;
        toReturn[i] = index;
    }

    return toReturn;
}
朱染 2025-01-25 04:19:39

另一件事:您可以使用反射。如果您正确地缓存,则它将在5.6秒内克隆1,000,000个对象(可悲的是,内在对象为16.4秒)。

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Person
{
       ...
      Job JobDescription
       ...
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}

private static readonly Type stringType = typeof (string);

public static class CopyFactory
{
    static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();

    private static readonly MethodInfo CreateCopyReflectionMethod;

    static CopyFactory()
    {
        CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
    }

    public static T CreateCopyReflection<T>(T source) where T : new()
    {
        var copyInstance = new T();
        var sourceType = typeof(T);

        PropertyInfo[] propList;
        if (ProperyList.ContainsKey(sourceType))
            propList = ProperyList[sourceType];
        else
        {
            propList = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            ProperyList.Add(sourceType, propList);
        }

        foreach (var prop in propList)
        {
            var value = prop.GetValue(source, null);
            prop.SetValue(copyInstance,
                value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
        }

        return copyInstance;
    }

我通过使用观察者类以简单的方式测量它。

 var person = new Person
 {
     ...
 };

 for (var i = 0; i < 1000000; i++)
 {
    personList.Add(person);
 }
 var watcher = new Stopwatch();
 watcher.Start();
 var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
 watcher.Stop();
 var elapsed = watcher.Elapsed;

结果:带有内在对象PersonInstance -16.4,PersonInstance = Null -5.6

CopyFactory只是我的测试类,其中我进行了多次测试,包括表达使用。您可以以扩展名或其他方式以另一种形式实施。不要忘记缓存。

我还没有测试序列化,但是我怀疑一百万个课程的改进。我将尝试一些快速的Protobuf/Newton。

PS:为了阅读简单性,我在这里只使用了自动Property。我可以使用fieldInfo进行更新,或者您应该自行轻松实现。

我最近测试了“ nofollow noreferrer”>“协议缓冲器”> serialializer serializer in the Box中的DeepClone函数。它以100万个简单对象的4.2秒获胜,但是当涉及内部对象时,结果赢得了7.4秒。

Serializer.DeepClone(personList);

摘要:如果您无法访问这些课程,那么这将有所帮助。否则,这取决于对象的计数。我认为您可以使用最多10,000个对象(也许少一点)的反射,但是对于此而言,协议缓冲序列化器的性能还会更好。

Another thing: you could use reflection. If you'll cache this properly, then it'll clone 1,000,000 objects in 5.6 seconds (sadly, 16.4 seconds with inner objects).

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Person
{
       ...
      Job JobDescription
       ...
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}

private static readonly Type stringType = typeof (string);

public static class CopyFactory
{
    static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();

    private static readonly MethodInfo CreateCopyReflectionMethod;

    static CopyFactory()
    {
        CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
    }

    public static T CreateCopyReflection<T>(T source) where T : new()
    {
        var copyInstance = new T();
        var sourceType = typeof(T);

        PropertyInfo[] propList;
        if (ProperyList.ContainsKey(sourceType))
            propList = ProperyList[sourceType];
        else
        {
            propList = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            ProperyList.Add(sourceType, propList);
        }

        foreach (var prop in propList)
        {
            var value = prop.GetValue(source, null);
            prop.SetValue(copyInstance,
                value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
        }

        return copyInstance;
    }

I measured it in a simple way, by using the Watcher class.

 var person = new Person
 {
     ...
 };

 for (var i = 0; i < 1000000; i++)
 {
    personList.Add(person);
 }
 var watcher = new Stopwatch();
 watcher.Start();
 var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
 watcher.Stop();
 var elapsed = watcher.Elapsed;

RESULT: With inner object PersonInstance - 16.4, PersonInstance = null - 5.6

CopyFactory is just my test class where I have dozen of tests including usage of expression. You could implement this in another form in an extension or whatever. Don't forget about caching.

I didn't test serializing yet, but I doubt in an improvement with a million classes. I'll try something fast protobuf/newton.

P.S.: for the sake of reading simplicity, I only used auto-property here. I could update with FieldInfo, or you should easily implement this by your own.

I recently tested the Protocol Buffers serializer with the DeepClone function out of the box. It wins with 4.2 seconds on a million simple objects, but when it comes to inner objects, it wins with the result 7.4 seconds.

Serializer.DeepClone(personList);

SUMMARY: If you don't have access to the classes, then this will help. Otherwise it depends on the count of the objects. I think you could use reflection up to 10,000 objects (maybe a bit less), but for more than this the Protocol Buffers serializer will perform better.

廻憶裏菂餘溫 2025-01-25 04:19:39

有一种简单的方法可以使用 JSON 序列化器和反序列化器来克隆 C# 中的对象。

您可以创建一个扩展类:

using Newtonsoft.Json;

static class typeExtensions
{
    [Extension()]
    public static T jsonCloneObject<T>(T source)
    {
    string json = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(json);
    }
}

克隆和对象:

obj clonedObj = originalObj.jsonCloneObject;

There is a simple way to clone objects in C# using a JSON serializer and deserializer.

You can create an extension class:

using Newtonsoft.Json;

static class typeExtensions
{
    [Extension()]
    public static T jsonCloneObject<T>(T source)
    {
    string json = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(json);
    }
}

To clone and object:

obj clonedObj = originalObj.jsonCloneObject;
暖伴 2025-01-25 04:19:39

对于深度克隆,我使用反射,如下所示:

public List<T> CloneList<T>(IEnumerable<T> listToClone) {
    Type listType = listToClone.GetType();
    Type elementType = listType.GetGenericArguments()[0];
    List<T> listCopy = new List<T>();
    foreach (T item in listToClone) {
        object itemCopy = Activator.CreateInstance(elementType);
        foreach (PropertyInfo property in elementType.GetProperties()) {
            elementType.GetProperty(property.Name).SetValue(itemCopy, property.GetValue(item));
        }
        listCopy.Add((T)itemCopy);
    }
    return listCopy;
}

您可以互换使用 List 或 IEnumerable。

For a deep clone I use reflection as follows:

public List<T> CloneList<T>(IEnumerable<T> listToClone) {
    Type listType = listToClone.GetType();
    Type elementType = listType.GetGenericArguments()[0];
    List<T> listCopy = new List<T>();
    foreach (T item in listToClone) {
        object itemCopy = Activator.CreateInstance(elementType);
        foreach (PropertyInfo property in elementType.GetProperties()) {
            elementType.GetProperty(property.Name).SetValue(itemCopy, property.GetValue(item));
        }
        listCopy.Add((T)itemCopy);
    }
    return listCopy;
}

You can use List or IEnumerable interchangeably.

眼角的笑意。 2025-01-25 04:19:39

它可以使用不同的参考来复制现有列表。在C#中执行此操作的最简单方法是DeepClone选项。

List<YourType> oldList = new List<YourType>();
var newList= oldList.DeepClone(); //Create a new memory reference

It may work to copy the existing list with a different reference. The simplest way to do this in C# is the DeepClone option.

List<YourType> oldList = new List<YourType>();
var newList= oldList.DeepClone(); //Create a new memory reference
凡尘雨 2025-01-25 04:19:38

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

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

但是,如果它们是引用类型并且您想要深层复制(假设您的元素正确实现了ICloneable),您可以这样做:

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

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

显然,替换上述泛型中的 ICloneable 并使用实现 ICloneable 的任何元素类型进行转换。

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

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

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

就个人而言,我会避免使用 ICloneable 因为需要保证所有成员的深拷贝。相反,我建议使用复制构造函数或像 YourType.CopyFrom(YourType itemToCopy) 这样的工厂方法,它返回 YourType 的新实例。

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

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:

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

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

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

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

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 ICloneable because 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.

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

两相知 2025-01-25 04:19:38

您可以使用扩展方法。

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

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();
    }
}
寻找一个思念的角度 2025-01-25 04:19:38

对于浅拷贝,您可以使用通用 List 类的 GetRange 方法。

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

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

引用自: 泛型食谱

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

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

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

Quoted from: Generics Recipes

两人的回忆 2025-01-25 04:19:38
public static object DeepClone(object obj) 
{
    object objResult = null;

    using (var ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, obj);

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

     return objResult;
}

这是使用C#和.NET 2.0进行操作的一种方法。您的对象需要为[serializable()]。目标是失去所有参考资料并建立新的参考。

public static object DeepClone(object obj) 
{
    object objResult = null;

    using (var ms = new MemoryStream())
    {
        var 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.

情独悲 2025-01-25 04:19:38

要克隆列表,只需调用.tolist()。这创建了浅副本。

Microsoft (R) Roslyn C# Compiler version 2.3.2.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
> 

To clone a list just call .ToList(). This creates a shallow copy.

Microsoft (R) Roslyn C# Compiler version 2.3.2.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
> 
深海少女心 2025-01-25 04:19:38

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

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

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;
}
渡你暖光 2025-01-25 04:19:38

除非您需要list&lt; t&gt;中每个对象的实际克隆,否则克隆列表的最佳方法是创建一个新列表,其中旧列表作为集合参数。

List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);

更改myList(例如插入或删除)不会影响cloneofmylist,反之亦然。

但是,两个列表包含的实际对象仍然相同。

Unless you need an actual clone of every single object inside your List<T>, the best way to clone a list is to create a new list with the old list as the collection parameter.

List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);

Changes to myList such as insert or remove will not affect cloneOfMyList and vice versa.

The actual objects the two Lists contain are still the same however.

一个人的旅程 2025-01-25 04:19:38

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

定义您的映射:

Mapper.CreateMap<YourType, YourType>();

发挥魔法:

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

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

Define your mapping:

Mapper.CreateMap<YourType, YourType>();

Do the magic:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);
双马尾 2025-01-25 04:19:38

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

并且您知道类型:

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

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

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

只是:

List<string> myNewList = Clone(myOldList);

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);
旧竹 2025-01-25 04:19:38

如果您已经在项目中引用了newtonsoft.json,并且您的对象是可序列化的,则可以始终使用:

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

可能不是最有效的方法,但是除非您这样做1000次1000次,否则您甚至可能不会注意到速度不同之处。

If you have already referenced Newtonsoft.Json in your project and your objects are serializeable you could always use:

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

Possibly not the most efficient way to do it, but unless you're doing it 100s of 1000s of times you may not even notice the speed difference.

给不了的爱 2025-01-25 04:19:38

对于深层副本,可观的是正确的解决方案,但这是使用构造函数而不是可lon式接口的类似方法。

public class Student
{
  public Student(Student student)
  {
    FirstName = student.FirstName;
    LastName = student.LastName;
  }

  public string FirstName { get; set; }
  public string LastName { get; set; }
}

// wherever you have the list
List<Student> students;

// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(s)).ToList();

您将需要以下库进行副本,

using System.Linq

也可以使用循环而不是System.linq,但是Linq使其简洁明了。同样,您可以像其他答案所建议的那样做并制定扩展方法等,但是这些都不是必需的。

For a deep copy, ICloneable is the correct solution, but here's a similar approach to ICloneable using the constructor instead of the ICloneable interface.

public class Student
{
  public Student(Student student)
  {
    FirstName = student.FirstName;
    LastName = student.LastName;
  }

  public string FirstName { get; set; }
  public string LastName { get; set; }
}

// wherever you have the list
List<Student> students;

// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(s)).ToList();

you'll need the following library where you make the copy

using System.Linq

you could also use a for loop instead of System.Linq, but Linq makes it concise and clean. Likewise you could do as other answers have suggested and make extension methods, etc., but none of that is necessary.

-小熊_ 2025-01-25 04:19:38

如果有人读过这个,我会很幸运...但是为了不在我的克隆方法中返回类型对象列表,我创建了一个接口:

public interface IMyCloneable<T>
{
    T Clone();
}

然后我指定了扩展名:

public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
    return listToClone.Select(item => (T)item.Clone()).ToList();
}

这是我的接口中的接口的实现音视频标记软件。我想让我的 Clone() 方法返回 VidMark 列表(而 ICloneable 接口希望我的方法返回对象列表):

public class VidMark : IMyCloneable<VidMark>
{
    public long Beg { get; set; }
    public long End { get; set; }
    public string Desc { get; set; }
    public int Rank { get; set; } = 0;

    public VidMark Clone()
    {
        return (VidMark)this.MemberwiseClone();
    }
}

最后,在类中使用扩展:

private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;

//Other methods instantiate and fill the lists

private void SetUndoVidMarks()
{
    _UndoVidMarks = _VidMarks.Clone();
}

有人喜欢吗?有什么改进吗?

I'll be lucky if anybody ever reads this... but in order to not return a list of type object in my Clone methods, I created an interface:

public interface IMyCloneable<T>
{
    T Clone();
}

Then I specified the extension:

public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
    return listToClone.Select(item => (T)item.Clone()).ToList();
}

And here is an implementation of the interface in my A/V marking software. I wanted to have my Clone() method return a list of VidMark (while the ICloneable interface wanted my method to return a list of object):

public class VidMark : IMyCloneable<VidMark>
{
    public long Beg { get; set; }
    public long End { get; set; }
    public string Desc { get; set; }
    public int Rank { get; set; } = 0;

    public VidMark Clone()
    {
        return (VidMark)this.MemberwiseClone();
    }
}

And finally, the usage of the extension inside a class:

private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;

//Other methods instantiate and fill the lists

private void SetUndoVidMarks()
{
    _UndoVidMarks = _VidMarks.Clone();
}

Anybody like it? Any improvements?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文