Как мне клонировать общий список в C #? - PullRequest
518 голосов
/ 21 октября 2008

У меня есть общий список объектов в C #, и я хочу клонировать этот список. Элементы в списке являются клонируемыми, но, похоже, нет возможности сделать list.Clone().

Есть ли простой способ обойти это?

Ответы [ 26 ]

3 голосов
/ 10 апреля 2016
    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;
        }
    }
3 голосов
/ 07 октября 2011
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;
  }
}
3 голосов
/ 25 апреля 2011
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;
}
2 голосов
/ 07 июня 2013

Вы можете использовать метод расширения:

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

Примечание: если вы внесете какие-либо изменения в копию (или клон), это не повлияет на исходный объект.

2 голосов
/ 15 января 2015

Вы также можете просто преобразовать список в массив, используя ToArray, а затем клонировать массив, используя Array.Clone(...). В зависимости от ваших потребностей методы, включенные в класс Array, могут удовлетворить ваши потребности.

2 голосов
/ 09 ноября 2016

Мой друг Грегор Мартинович и я придумали это простое решение с использованием JavaScript-сериализатора. Нет необходимости отмечать классы как Serializable, и в наших тестах использование Newtonsoft JsonSerializer даже быстрее, чем использование BinaryFormatter. С методами расширения, применимыми к каждому объекту.

Стандартная опция .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);
}
2 голосов
/ 22 декабря 2015

Если вам нужен клонированный список с такой же емкостью, вы можете попробовать это:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}
1 голос
/ 27 февраля 2019

Использование приведения может быть полезно, в этом случае, для мелкой копии:

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);
1 голос
/ 03 июля 2013

Я сделал для себя какое-то расширение, которое преобразует ICollection элементов, не поддерживающих 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();
    }
}
1 голос
/ 13 октября 2014

Я использую Autopper для копирования объекта. Я просто настроил отображение, которое отображает один объект на себя. Вы можете обернуть эту операцию любым удобным вам способом.

http://automapper.codeplex.com/

...