Jak zrobić głęboką kopię obiektu in.NET? [duplikat]

to pytanie ma już odpowiedzi tutaj : Głębokie klonowanie obiektów (48 odpowiedzi) Zamknięte 6 lat ago .

Chcę prawdziwej, głębokiej kopii. W Javie to było proste, ale jak to zrobić w C#?

Author: Uwe Keim, 2008-09-24

11 answers

Widziałem kilka różnych podejść do tego, ale używam ogólnej metody użytkowej jako takiej:

public static T DeepClone<T>(this T obj)
{
 using (var ms = new MemoryStream())
 {
   var formatter = new BinaryFormatter();
   formatter.Serialize(ms, obj);
   ms.Position = 0;

   return (T) formatter.Deserialize(ms);
 }
}

Uwagi:

  • twoja klasa musi być oznaczona jako [Serializable] aby to zadziałało.
  • Twój plik źródłowy musi zawierać następujący kod:

    using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;
    
 680
Author: Kilhoffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-04 06:02:10

I napisał metodę rozszerzenia głębokiego kopiowania obiektów , opartą na rekurencyjnym "MemberwiseClone". Jest szybki (trzy razy szybszy niż BinaryFormatter) i działa z dowolnym obiektem. Nie potrzebujesz domyślnego konstruktora ani serializowalnych atrybutów.

Kod źródłowy:

using System.Collections.Generic;
using System.Reflection;
using System.ArrayExtensions;

namespace System
{
    public static class ObjectExtensions
    {
        private static readonly MethodInfo CloneMethod = typeof(Object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);

        public static bool IsPrimitive(this Type type)
        {
            if (type == typeof(String)) return true;
            return (type.IsValueType & type.IsPrimitive);
        }

        public static Object Copy(this Object originalObject)
        {
            return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
        }
        private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
        {
            if (originalObject == null) return null;
            var typeToReflect = originalObject.GetType();
            if (IsPrimitive(typeToReflect)) return originalObject;
            if (visited.ContainsKey(originalObject)) return visited[originalObject];
            if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
            var cloneObject = CloneMethod.Invoke(originalObject, null);
            if (typeToReflect.IsArray)
            {
                var arrayType = typeToReflect.GetElementType();
                if (IsPrimitive(arrayType) == false)
                {
                    Array clonedArray = (Array)cloneObject;
                    clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
                }

            }
            visited.Add(originalObject, cloneObject);
            CopyFields(originalObject, visited, cloneObject, typeToReflect);
            RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
            return cloneObject;
        }

        private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
        {
            if (typeToReflect.BaseType != null)
            {
                RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
                CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
            }
        }

        private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
        {
            foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
            {
                if (filter != null && filter(fieldInfo) == false) continue;
                if (IsPrimitive(fieldInfo.FieldType)) continue;
                var originalFieldValue = fieldInfo.GetValue(originalObject);
                var clonedFieldValue = InternalCopy(originalFieldValue, visited);
                fieldInfo.SetValue(cloneObject, clonedFieldValue);
            }
        }
        public static T Copy<T>(this T original)
        {
            return (T)Copy((Object)original);
        }
    }

    public class ReferenceEqualityComparer : EqualityComparer<Object>
    {
        public override bool Equals(object x, object y)
        {
            return ReferenceEquals(x, y);
        }
        public override int GetHashCode(object obj)
        {
            if (obj == null) return 0;
            return obj.GetHashCode();
        }
    }

    namespace ArrayExtensions
    {
        public static class ArrayExtensions
        {
            public static void ForEach(this Array array, Action<Array, int[]> action)
            {
                if (array.LongLength == 0) return;
                ArrayTraverse walker = new ArrayTraverse(array);
                do action(array, walker.Position);
                while (walker.Step());
            }
        }

        internal class ArrayTraverse
        {
            public int[] Position;
            private int[] maxLengths;

            public ArrayTraverse(Array array)
            {
                maxLengths = new int[array.Rank];
                for (int i = 0; i < array.Rank; ++i)
                {
                    maxLengths[i] = array.GetLength(i) - 1;
                }
                Position = new int[array.Rank];
            }

            public bool Step()
            {
                for (int i = 0; i < Position.Length; ++i)
                {
                    if (Position[i] < maxLengths[i])
                    {
                        Position[i]++;
                        for (int j = 0; j < i; j++)
                        {
                            Position[j] = 0;
                        }
                        return true;
                    }
                }
                return false;
            }
        }
    }

}
 365
Author: Alex Burtsev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-10 10:36:42

Bazując na rozwiązaniu Kilhoffera...

W C # 3.0 można utworzyć metodę rozszerzenia w następujący sposób:

public static class ExtensionMethods
{
    // Deep clone
    public static T DeepClone<T>(this T a)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, a);
            stream.Position = 0;
            return (T) formatter.Deserialize(stream);
        }
    }
}

Który rozszerza dowolną klasę, która została oznaczona jako [Serializowalna] za pomocą metody DeepClone

MyClass copy = obj.DeepClone();
 172
Author: Neil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 15:03:41

Możesz użyć zagnieżdżonego MemberwiseClone, aby wykonać głęboką kopię. Jego prawie taka sama szybkość jak kopiowanie struktury wartości, a jego rząd wielkości jest szybszy niż (a) odbicie lub (b) serializacja (jak opisano w innych odpowiedziach na tej stronie).

Zauważ, że Jeśli używasz zagnieżdżonego MemberwiseClone do głębokiej kopii , musisz ręcznie zaimplementować ShallowCopy dla każdego zagnieżdżonego poziomu w klasie oraz DeepCopy, który wywołuje wszystkie wymienione metody ShallowCopy, aby utworzyć kompletny klon. To proste: w sumie tylko kilka linijek, zobacz poniższy kod demonstracyjny.

Oto wynik kodu pokazujący względną różnicę wydajności (4,77 sekundy dla głębokiego zagnieżdżenia MemberwiseCopy vs.39,93 sekundy dla serializacji). Używanie zagnieżdżonego MemberwiseCopy jest prawie tak szybkie jak kopiowanie struktury, a kopiowanie struktury jest całkiem bliskie teoretycznej maksymalnej prędkości. NET, do której jest zdolne, co prawdopodobnie jest bliskie prędkości tego samego w C lub C++ (ale musiałoby Uruchom kilka równoważnych benchmarków, aby sprawdzić to twierdzenie).

    Demo of shallow and deep copy, using classes and MemberwiseClone:
      Create Bob
        Bob.Age=30, Bob.Purchase.Description=Lamborghini
      Clone Bob >> BobsSon
      Adjust BobsSon details
        BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
      Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
        Bob.Age=30, Bob.Purchase.Description=Lamborghini
      Elapsed time: 00:00:04.7795670,30000000
    Demo of shallow and deep copy, using structs and value copying:
      Create Bob
        Bob.Age=30, Bob.Purchase.Description=Lamborghini
      Clone Bob >> BobsSon
      Adjust BobsSon details:
        BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
      Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
        Bob.Age=30, Bob.Purchase.Description=Lamborghini
      Elapsed time: 00:00:01.0875454,30000000
    Demo of deep copy, using class and serialize/deserialize:
      Elapsed time: 00:00:39.9339425,30000000

Aby zrozumieć, jak zrobić głęboką kopię używając MemberwiseCopy, oto projekt demo:

// Nested MemberwiseClone example. 
// Added to demo how to deep copy a reference class.
[Serializable] // Not required if using MemberwiseClone, only used for speed comparison using serialization.
public class Person
{
    public Person(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    [Serializable] // Not required if using MemberwiseClone
    public class PurchaseType
    {
        public string Description;
        public PurchaseType ShallowCopy()
        {
            return (PurchaseType)this.MemberwiseClone();
        }
    }
    public PurchaseType Purchase = new PurchaseType();
    public int Age;
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person ShallowCopy()
    {
        return (Person)this.MemberwiseClone();
    }
    // Add this if using nested MemberwiseClone.
    // This is a class, which is a reference type, so cloning is more difficult.
    public Person DeepCopy()
    {
            // Clone the root ...
        Person other = (Person) this.MemberwiseClone();
            // ... then clone the nested class.
        other.Purchase = this.Purchase.ShallowCopy();
        return other;
    }
}
// Added to demo how to copy a value struct (this is easy - a deep copy happens by default)
public struct PersonStruct
{
    public PersonStruct(int age, string description)
    {
        this.Age = age;
        this.Purchase.Description = description;
    }
    public struct PurchaseType
    {
        public string Description;
    }
    public PurchaseType Purchase;
    public int Age;
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct ShallowCopy()
    {
        return (PersonStruct)this;
    }
    // This is a struct, which is a value type, so everything is a clone by default.
    public PersonStruct DeepCopy()
    {
        return (PersonStruct)this;
    }
}
// Added only for a speed comparison.
public class MyDeepCopy
{
    public static T DeepCopy<T>(T obj)
    {
        object result = null;
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, obj);
            ms.Position = 0;
            result = (T)formatter.Deserialize(ms);
            ms.Close();
        }
        return (T)result;
    }
}

Następnie wywołaj demo z main:

    void MyMain(string[] args)
    {
        {
            Console.Write("Demo of shallow and deep copy, using classes and MemberwiseCopy:\n");
            var Bob = new Person(30, "Lamborghini");
            Console.Write("  Create Bob\n");
            Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
            Console.Write("  Clone Bob >> BobsSon\n");
            var BobsSon = Bob.DeepCopy();
            Console.Write("  Adjust BobsSon details\n");
            BobsSon.Age = 2;
            BobsSon.Purchase.Description = "Toy car";
            Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
            Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
            Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
            Debug.Assert(Bob.Age == 30);
            Debug.Assert(Bob.Purchase.Description == "Lamborghini");
            var sw = new Stopwatch();
            sw.Start();
            int total = 0;
            for (int i = 0; i < 100000; i++)
            {
                var n = Bob.DeepCopy();
                total += n.Age;
            }
            Console.Write("  Elapsed time: {0},{1}\n", sw.Elapsed, total);
        }
        {               
            Console.Write("Demo of shallow and deep copy, using structs:\n");
            var Bob = new PersonStruct(30, "Lamborghini");
            Console.Write("  Create Bob\n");
            Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
            Console.Write("  Clone Bob >> BobsSon\n");
            var BobsSon = Bob.DeepCopy();
            Console.Write("  Adjust BobsSon details:\n");
            BobsSon.Age = 2;
            BobsSon.Purchase.Description = "Toy car";
            Console.Write("    BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
            Console.Write("  Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
            Console.Write("    Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);                
            Debug.Assert(Bob.Age == 30);
            Debug.Assert(Bob.Purchase.Description == "Lamborghini");
            var sw = new Stopwatch();
            sw.Start();
            int total = 0;
            for (int i = 0; i < 100000; i++)
            {
                var n = Bob.DeepCopy();
                total += n.Age;
            }
            Console.Write("  Elapsed time: {0},{1}\n", sw.Elapsed, total);
        }
        {
            Console.Write("Demo of deep copy, using class and serialize/deserialize:\n");
            int total = 0;
            var sw = new Stopwatch();
            sw.Start();
            var Bob = new Person(30, "Lamborghini");
            for (int i = 0; i < 100000; i++)
            {
                var BobsSon = MyDeepCopy.DeepCopy<Person>(Bob);
                total += BobsSon.Age;
            }
            Console.Write("  Elapsed time: {0},{1}\n", sw.Elapsed, total);
        }
        Console.ReadKey();
    }

Ponownie zauważ, że Jeśli używasz zagnieżdżonego MemberwiseClone do głębokiej kopii, musisz ręcznie zaimplementować ShallowCopy dla każdego zagnieżdżonego poziomu w klasie oraz DeepCopy, który wywołuje wszystkie wymienione metody ShallowCopy, aby utworzyć kompletny klon. Jest to proste: tylko a kilka linijek w sumie, zobacz kod demo powyżej.

Zauważ, że jeśli chodzi o klonowanie obiektu, istnieje duża różnica między "strukturą" a "klasą":

  • jeśli masz "struct", jest to typ wartości, więc możesz go skopiować, a zawartość zostanie sklonowana.
  • jeśli masz "klasę", jest to typ odniesienia, więc jeśli ją skopiujesz, jedyne co robisz, to kopiujesz wskaźnik do niej. Aby stworzyć prawdziwy klon, musisz być bardziej kreatywny i użyć metody, która tworzy kolejna kopia oryginalnego obiektu w pamięci.
  • niepoprawne klonowanie obiektów może prowadzić do bardzo trudnych do zidentyfikowania błędów. W kodzie produkcyjnym implementuję sumę kontrolną, aby dokładnie sprawdzić, czy obiekt został poprawnie sklonowany i czy nie został uszkodzony przez inne odniesienie do niego. Tę sumę kontrolną można wyłączyć w trybie Release.
  • uważam, że ta metoda jest bardzo przydatna: często chcesz tylko klonować części obiektu, a nie całą rzecz. Jest również niezbędny do każdego zastosowania przypadek, w którym modyfikujesz obiekty, a następnie wprowadzasz zmodyfikowane kopie do kolejki.

Update

Prawdopodobnie możliwe jest użycie odbicia do rekurencyjnego przechodzenia przez wykres obiektu w celu wykonania głębokiej kopii. WCF wykorzystuje tę technikę do serializacji obiektu, w tym wszystkich jego dzieci. Sztuczka polega na przypisaniu wszystkich obiektów potomnych atrybutem, który sprawia, że są one wykrywalne. Możesz stracić pewne korzyści z wydajności, jednak.

Update

Cytat z niezależnego testu prędkości (patrz komentarze poniżej):

Przeprowadziłem własny test prędkości przy użyciu serialize/deserialize Neila metoda rozszerzenia, zagnieżdżone MemberwiseClone Contango, Alex Burtsev metoda rozszerzania oparta na odbiciach i AutoMapper, 1 milion razy każdy. Serialize-deserialize był najwolniejszy, zajmując 15,7 sekundy. Wtedy przyszedł AutoMapper, zajmując 10,1 sekundy. Znacznie szybciej było metoda refleksyjna, która zajęła 2.4 sekund. Zdecydowanie najszybszy był Zagnieżdżone MemberwiseClone, trwa 0,1 sekundy. Sprowadza się do wydajności zamiast kłopotów z dodawaniem kodu do każdej klasy w celu jego sklonowania. IF performance to nie problem z metodą Alexa Burtseva. - Simon Tewsi

 56
Author: Contango,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-09 18:43:23

Uważam, że podejście BinaryFormatter jest stosunkowo powolny (co było dla mnie zaskoczeniem!). Możesz być w stanie użyć ProtoBuf.net dla niektórych obiektów, jeśli spełniają one wymagania ProtoBuf. Ze strony Protobuf pierwsze kroki ( http://code.google.com/p/protobuf-net/wiki/GettingStarted):

Uwagi dotyczące obsługiwanych typów:

Klasy niestandardowe, które:

  • są oznaczone jako data-contract
  • mieć parametr bez konstruktor
  • Dla Silverlight: są publiczne
  • wiele pospolitych prymitywów, itp.
  • pojedyncze tablice wymiarów: T []
  • List / IList
  • Słownik / IDictionary
  • każdy typ, który implementuje IEnumerable i ma metodę Add (T)

Kodeks zakłada, że typy będą zmienne wokół wybranych członków. W związku z tym niestandardowe struktury nie są obsługiwane, ponieważ powinny być niezmienny.

Jeśli twoja klasa spełnia te wymagania, możesz spróbować:

public static void deepCopy<T>(ref T object2Copy, ref T objectCopy)
{
    using (var stream = new MemoryStream())
    {
        Serializer.Serialize(stream, object2Copy);
        stream.Position = 0;
        objectCopy = Serializer.Deserialize<T>(stream);
    }
}
Co jest naprawdę bardzo szybkie...

Edit:

Oto kod roboczy dla modyfikacji tego (testowany na. Net 4.6). Wykorzystuje System.Xml.Serializacja i System.IO. nie ma potrzeby oznaczania klas jako serializowalnych.

public void DeepCopy<T>(ref T object2Copy, ref T objectCopy)
{
    using (var stream = new MemoryStream())
    {
        var serializer = new XS.XmlSerializer(typeof(T));

        serializer.Serialize(stream, object2Copy);
        stream.Position = 0;
        objectCopy = (T)serializer.Deserialize(stream);
    }
}
 21
Author: Kurt Richardson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-20 12:03:59

Możesz spróbować tego

    public static object DeepCopy(object obj)
    {
        if (obj == null)
            return null;
        Type type = obj.GetType();

        if (type.IsValueType || type == typeof(string))
        {
            return obj;
        }
        else if (type.IsArray)
        {
            Type elementType = Type.GetType(
                 type.FullName.Replace("[]", string.Empty));
            var array = obj as Array;
            Array copied = Array.CreateInstance(elementType, array.Length);
            for (int i = 0; i < array.Length; i++)
            {
                copied.SetValue(DeepCopy(array.GetValue(i)), i);
            }
            return Convert.ChangeType(copied, obj.GetType());
        }
        else if (type.IsClass)
        {

            object toret = Activator.CreateInstance(obj.GetType());
            FieldInfo[] fields = type.GetFields(BindingFlags.Public |
                        BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo field in fields)
            {
                object fieldValue = field.GetValue(obj);
                if (fieldValue == null)
                    continue;
                field.SetValue(toret, DeepCopy(fieldValue));
            }
            return toret;
        }
        else
            throw new ArgumentException("Unknown type");
    }

Dzięki DetoX83 Artykuł o projekcie code.

 8
Author: Suresh Kumar Veluswamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-01 03:59:40

Może potrzebujesz tylko płytkiej kopii, w tym przypadku użyj Object.MemberWiseClone().

Istnieją dobre zalecenia w dokumentacji MemberWiseClone() dla strategii głębokiego kopiowania: -

Http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx

 4
Author: David Thornley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-04 19:33:54

Najlepszy sposób to:

    public interface IDeepClonable<T> where T : class
    {
        T DeepClone();
    }

    public class MyObj : IDeepClonable<MyObj>
    {
        public MyObj Clone()
        {
            var myObj = new MyObj();
            myObj._field1 = _field1;//value type
            myObj._field2 = _field2;//value type
            myObj._field3 = _field3;//value type

            if (_child != null)
            {
                myObj._child = _child.DeepClone(); //reference type .DeepClone() that does the same
            }

            int len = _array.Length;
            myObj._array = new MyObj[len]; // array / collection
            for (int i = 0; i < len; i++)
            {
                myObj._array[i] = _array[i];
            }

            return myObj;
        }

        private bool _field1;
        public bool Field1
        {
            get { return _field1; }
            set { _field1 = value; }
        }

        private int _field2;
        public int Property2
        {
            get { return _field2; }
            set { _field2 = value; }
        }

        private string _field3;
        public string Property3
        {
            get { return _field3; }
            set { _field3 = value; }
        }

        private MyObj _child;
        private MyObj Child
        {
            get { return _child; }
            set { _child = value; }
        }

        private MyObj[] _array = new MyObj[4];
    }
 4
Author: alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-02 21:47:19
    public static object CopyObject(object input)
    {
        if (input != null)
        {
            object result = Activator.CreateInstance(input.GetType());
            foreach (FieldInfo field in input.GetType().GetFields(Consts.AppConsts.FullBindingList))
            {
                if (field.FieldType.GetInterface("IList", false) == null)
                {
                    field.SetValue(result, field.GetValue(input));
                }
                else
                {
                    IList listObject = (IList)field.GetValue(result);
                    if (listObject != null)
                    {
                        foreach (object item in ((IList)field.GetValue(input)))
                        {
                            listObject.Add(CopyObject(item));
                        }
                    }
                }
            }
            return result;
        }
        else
        {
            return null;
        }
    }

Ten sposób jest kilka razy szybszy niż BinarySerialization i nie wymaga atrybutu [Serializable].

 1
Author: Basil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-17 21:11:28

Dokumentacja MSDN wydaje się wskazywać, że Clone powinien wykonać głęboką kopię, ale nigdy nie jest to wyraźnie powiedziane:

Interfejs ICloneable zawiera jednego członka, Clone, który jest przeznaczony do obsługi klonowania poza dostarczonym przez MemberWiseClone ... metoda MemberwiseClone tworzy płytką kopię ...

Mój post może być pomocny.

Http://pragmaticcoding.com/index.php/cloning-objects-in-c/

 0
Author: Eugene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-13 13:50:01

Mam prostszy pomysł. Użyj LINQ z nową selekcją.

public class Fruit
{
  public string Name {get; set;}
  public int SeedCount {get; set;}
}

void SomeMethod()
{
  List<Fruit> originalFruits = new List<Fruit>();
  originalFruits.Add(new Fruit {Name="Apple", SeedCount=10});
  originalFruits.Add(new Fruit {Name="Banana", SeedCount=0});

  //Deep Copy
  List<Fruit> deepCopiedFruits = from f in originalFruits
              select new Fruit {Name=f.Name, SeedCount=f.SeedCount};
}
 -7
Author: Jordan Morris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-02 21:49:50