Что такое клонирование (Clone) объекта в C# и какие типы клонирования существуют?

«Что такое клонирование (Clone) объекта в C# и какие типы клонирования существуют?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Клонирование — это процесс создания нового объекта, который является копией существующего. В C# различают два основных типа клонирования, которые важно понимать для корректной работы с данными.

1. Поверхностное копирование (Shallow Copy)

Создает новый объект, но копирует значения полей. Для полей-значений (int, struct) копируется само значение. Для полей-ссылок копируется только ссылка, поэтому исходный и клонированный объекты делят одни и те же вложенные объекты.

Стандартный способ: Использование защищенного метода Object.MemberwiseClone().

public class Person
{
    public string Name; // Ссылочный тип
    public Address HomeAddress; // Ссылочный тип (класс)

    public Person ShallowClone()
    {
        // MemberwiseClone создает shallow copy
        return (Person)this.MemberwiseClone();
    }
}
// Использование:
var original = new Person { Name = "John", HomeAddress = new Address("Street 1") };
var shallowCopy = original.ShallowClone();
shallowCopy.Name = "Jane"; // Изменяется только копия
shallowCopy.HomeAddress.Street = "Street 2"; // Изменяет Address и у original, и у копии!

2. Глубокое копирование (Deep Copy)

Создает новый объект и рекурсивно создает копии всех объектов, на которые есть ссылки. В результате получается полностью независимая копия всего графа объектов.

Реализация требует ручных усилий или использования сериализации:

public Person DeepClone()
{
    var clone = (Person)this.MemberwiseClone();
    clone.Name = this.Name; // string неизменяем, можно просто присвоить
    clone.HomeAddress = new Address(this.HomeAddress.Street); // Создаем новый объект Address
    return clone;
}

Практический совет: Интерфейс ICloneable (object Clone()) считается устаревшим в контексте best practices, так как он не указывает, какой тип копирования реализуется. Гораздо яснее создавать явные методы ShallowClone() и DeepClone(). Для сложных графов объектов часто используют сериализацию (например, через System.Text.Json с настройкой ссылочной целостности) для реализации глубокого копирования.