Bagaimana cara clone daftar generik di C#?

Saya memiliki daftar generik objek di C#, dan berharap untuk mengkloning daftar. Item dalam daftar yang cloneable, tapi ada doesn't tampaknya menjadi pilihan untuk melakukan daftar.Clone().

Apakah ada cara mudah ini?

Mengomentari pertanyaan (7)

Jika unsur-unsur nilai jenis, maka anda hanya dapat melakukan:

List newList = new List(oldList);

Namun, jika mereka adalah jenis referensi dan anda ingin dalam salinan (dengan asumsi anda benar menerapkan unsur-unsur ICloneable), anda bisa melakukan sesuatu seperti ini:

List oldList = new List();
List newList = new List(oldList.Count);

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

Jelas, ganti ICloneable di atas obat generik dan cor dengan apa elemen anda adalah tipe yang menerapkan ICloneable.

Jika anda jenis elemen doesn't dukungan ICloneable tetapi tidak memiliki copy constructor, anda bisa melakukan hal ini sebagai gantinya:

List oldList = new List();
List newList = new List(oldList.Count);

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

Secara pribadi, saya akan menghindari ICloneable karena kebutuhan untuk menjamin dalam salinan dari semua anggota. Sebaliknya, saya'd sarankan copy-konstruktor atau metode pabrik seperti YourType.CopyFrom(YourType itemToCopy) yang mengembalikan sebuah instance baru dari YourType.

Setiap pilihan ini bisa dibungkus dengan metode (ekstensi atau sebaliknya).

Komentar (21)
Larutan

Anda dapat menggunakan metode penyuluhan.

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

Untuk salinan dangkal, anda dapat menggunakan GetRange metode generik Daftar kelas.

List oldList = new List( );
// Populate oldList...

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

Dikutip dari: Resep obat Generik

Komentar (2)
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;
}

Ini adalah salah satu cara untuk melakukannya dengan C# dan .NET 2.0. Objek anda membutuhkan untuk menjadi [Serializable()]. Tujuannya adalah untuk menurunkan semua referensi dan membangun yang baru.

Komentar (6)

Setelah sedikit modifikasi, anda juga bisa clone:

public static T DeepClone(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;
}
Komentar (2)

Untuk mengkloning daftar panggil .Kedaftar()

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

Kecuali anda butuhkan sebenarnya clone dari setiap objek di dalam Daftar<T>, cara terbaik untuk mengkloning daftar untuk membuat daftar baru dengan yang lama daftar sebagai koleksi parameter.

List myList = ...;
List cloneOfMyList = new List(myList);

Perubahan myList seperti menyisipkan atau menghapus tidak akan mempengaruhi cloneOfMyList dan sebaliknya.

Benda-benda yang sebenarnya dua Daftar yang berisi yang masih sama namun.

Komentar (5)

Jika anda hanya peduli tentang nilai jenis...

Dan anda tahu jenis:

List newList = new List(oldList);

Jika anda don't tahu jenis sebelumnya, anda'll membutuhkan fungsi pembantu:

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

Hanya:

List myNewList = Clone(myOldList);
Komentar (2)

Gunakan AutoMapper (atau apapun pemetaan lib anda sukai) untuk mengkloning sederhana dan banyak dipelihara.

Menentukan pemetaan:

Mapper.CreateMap();

Melakukan sihir:

YourTypeList.ConvertAll(Mapper.Map);
Komentar (0)

Jika anda sudah dirujuk Newtonsoft.Json dalam proyek anda dan benda-benda yang serializeable anda selalu bisa menggunakan:

List newList = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(listToCopy))

Mungkin bukan cara yang paling efisien untuk melakukannya, tetapi jika anda're melakukannya 100 1000s kali anda mungkin bahkan tidak menyadari perbedaan kecepatan.

Komentar (2)
 //try this
 List ListCopy= new List(OldList);
 //or try
 List ListCopy=OldList.ToList();
Komentar (0)
public class CloneableList : List, ICloneable where T : ICloneable
{
  public object Clone()
  {
    var clone = new List();
    ForEach(item => clone.Add((T)item.Clone()));
    return clone;
  }
}
Komentar (0)
    public List Clone(List o1List) where TEntity : class , new()
    {
        List retList = new List();
        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;
        }
    }
Komentar (0)
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;
}
Komentar (0)

I'akan beruntung jika ada yang pernah membaca ini... tapi dalam rangka untuk tidak kembali daftar tipe objek di Clone metode, aku menciptakan sebuah antarmuka:

public interface IMyCloneable
{
    T Clone();
}

Kemudian saya ditentukan ekstensi:

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

Dan berikut ini adalah implementasi antarmuka pada saya A/V menandai perangkat lunak. Saya ingin memiliki saya Clone() metode kembali daftar VidMark (sementara ICloneable antarmuka yang ingin saya metode untuk mengembalikan daftar objek):

public class VidMark : IMyCloneable
{
    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();
    }
}

Dan akhirnya, penggunaan ekstensi di dalam kelas:

private List _VidMarks;
private List _UndoVidMarks;

//Other methods instantiate and fill the lists

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

Orang seperti itu? Perbaikan?

Komentar (0)

Anda bisa juga hanya mengkonversi daftar ke array menggunakan ToArray, dan kemudian clone array menggunakan Array.Clone(...). Tergantung pada kebutuhan anda, metode yang termasuk dalam kelas Array bisa memenuhi kebutuhan anda.

Komentar (2)

Anda dapat menggunakan metode penyuluhan:

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

}

Anda dapat mengkloning semua benda dengan menggunakan nilai mereka jenis anggota misalnya, menganggap kelas ini:


public class matrix
{
    public List 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
        for(x=0;x
Komentar (0)

Jika anda membutuhkan kloning daftar dengan kapasitas yang sama, anda dapat mencoba ini:

public static List Clone(this List oldList)
{
    var newList = new List(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}
Komentar (0)

Teman saya Gregor Martinovic dan saya datang dengan ini solusi mudah menggunakan JavaScript Serializer. Ada tidak perlu untuk menandai kelas sebagai Serializable dan dalam pengujian kami menggunakan Newtonsoft JsonSerializer bahkan lebih cepat daripada menggunakan BinaryFormatter. Dengan metode ekstensi yang dapat digunakan pada setiap objek.

Standar .NET JavascriptSerializer pilihan:

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

    string json = js.Serialize(value);

    return js.Deserialize(json);
}

Lebih cepat menggunakan opsi Newtonsoft JSON:

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

    return JsonConvert.DeserializeObject(json);
}
Komentar (1)

Saya menggunakan automapper untuk menyalin suatu objek. Saya hanya men-setup sebuah pemetaan yang memetakan satu objek untuk dirinya sendiri. Anda dapat membungkus operasi ini cara apapun yang anda suka.

http://automapper.codeplex.com/

Komentar (0)