[ Полезный рекламный блок ]
Попробуйте свои силы в игре, где ваши навыки программирования на C# станут решающим фактором. Переходите по ссылке 🔰.
В C# клонирование объекта означает создание его копии. Однако существует два типа клонирования: неглубокое клонирование и глубокое клонирование.
При неглубоком клонировании создается новый объект, который является копией исходного объекта, но содержимое копии по-прежнему указывает на те же объекты, что и оригинал. Это означает, что изменения, внесенные в свойства копии, также повлияют на оригинал.
Глубокое клонирование, с другой стороны, создает новый объект, который является копией оригинала, но содержимое копии также копируется, поэтому у двух объектов нет общих ссылок. Это означает, что изменения, внесенные в свойства копии, не повлияют на оригинал.
В C# существует несколько способов глубокого клонирования объекта, включая реализацию интерфейса ICloneable, использование сериализации и десериализации, а также использование сторонних библиотек, таких как AutoMapper, Newtonsoft.Json или BinaryFormatter.
Сериализации и десериализация
Один из распространенных подходов — использование сериализации и десериализации. Вот пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; [Serializable] public class MyClass { public int Number { get; set; } public string Text { get; set; } } class Program { static void Main(string[] args) { MyClass original = new MyClass { Number = 42, Text = "Hello, World!" }; // Create a memory stream and binary formatter MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); // Serialize the object to the memory stream formatter.Serialize(stream, original); // Reset the stream position to the beginning stream.Position = 0; // Deserialize the object from the memory stream MyClass copy = (MyClass)formatter.Deserialize(stream); // Modify the copy's properties copy.Number = 24; copy.Text = "Goodbye, World!"; // The original's properties remain unchanged Console.WriteLine(original.Number); // Output: 42 Console.WriteLine(original.Text); // Output: Hello, World! // The copy's properties have been modified Console.WriteLine(copy.Number); // Output: 24 Console.WriteLine(copy.Text); // Output: Goodbye, World! } } |
В этом примере мы определяем простой класс MyClass, который имеет два свойства: Number и Text. Затем мы создаем экземпляр MyClass и сериализуем его в поток памяти с помощью BinaryFormatter. Мы сбрасываем позицию потока в начало, а затем десериализуем объект обратно в новый экземпляр MyClass под названием copy. Наконец, мы изменяем свойства копии и проверяем, что свойства оригинала остались неизменными.
Использование сериализации и десериализации предполагает сериализацию исходного объекта в поток байтов, а затем его десериализацию обратно в новый объект. Этот подход может быть медленнее, чем другие методы, но он часто проще в реализации.
Реализация интерфейса ICloneable
Для начала рассмотрим пример не глубокого клонирования:
1 2 3 4 5 6 7 8 9 |
class Person : ICloneable { public string Name { get; set; } public int Age { get; set; } public object Clone() { return new Person { Name = this.Name, Age = this.Age }; } } |
Использование:
1 2 3 4 5 6 7 |
static void Main() { Person p1 = new Person { Name = "Tom", Age = 23 }; Person p2 = (Person)p1.Clone(); p2.Name = "Alice"; Console.WriteLine(p1.Name); // Tom } |
Теперь, пример с глубоким клонированием:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Person : ICloneable { public string Name { get; set; } public int Age { get; set; } public Company Work { get; set; } public object Clone() { Company company = new Company { Name = this.Work.Name }; return new Person { Name = this.Name, Age = this.Age, Work = company }; } } |
Или можно сделать следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Person : ICloneable { public string Name { get; set; } public int Age { get; set; } public Company Work { get; set; } public object Clone() { var person = (Person)this.MemberwiseClone(); person.Work = (Company)this.Work.Clone(); return person; } } class Company:ICloneable { public string Name { get; set; } public object Clone() { return this.MemberwiseClone(); } } |
Использование:
1 2 3 4 5 6 7 8 9 |
static void Main(string[] args) { Person p1 = new Person { Name = "Tom", Age = 23, Work = new Company { Name = "Microsoft" } }; Person p2 = (Person)p1.Clone(); p2.Work.Name = "Google"; p2.Name = "Alice"; Console.WriteLine(p1.Name); Console.WriteLine(p1.Work.Name); } |