В Visual Basic часто необходимо создать копию объекта, чтобы изменять данные новым образом, не затрагивая исходную структуру. Возникает задача различать поверхностное (shallow) и глубокое (deep) копирование, особенно если объекты содержат вложенные ссылочные типы.
История вопроса:
Поверхностное копирование копирует только значения примитивных свойств и ссылки на вложенные объекты, а глубокое копирование создаёт новые экземпляры всех вложенных объектов. Различие принципиально при работе со сложными данными, например, если объект содержит коллекции или другие объекты.
Проблема:
Если скопировать объект по ссылке или воспользоваться стандартным методом MemberwiseClone, то при изменении вложенных объектов исходная структура изменится вместе с копией — это опасно для бизнес-логики и может привести к трудноуловимым багам.
Решение:
В VB.NET прямого готового глубокого копирования нет, поэтому его следует реализовывать вручную или через сериализацию. Обычно реализуют пользовательский метод DeepCopy, создавая новые экземпляры всех вложенных объектов.
Пример кода поверхностного и глубокого копирования:
Class Person Public Name As String Public Address As Address ' Поверхностное копирование Public Function ShallowCopy() As Person Return CType(Me.MemberwiseClone(), Person) End Function ' Глубокое копирование Public Function DeepCopy() As Person Dim copy As Person = CType(Me.MemberwiseClone(), Person) copy.Address = New Address() With {.City = Me.Address.City} Return copy End Function End Class Class Address Public City As String End Class
Ключевые особенности:
Что вернет оператор = при копировании объекта класса в Visual Basic?
Ответ: Оператор = для ссылочных типов присваивает ссылку, а не копирует значения. Поэтому обе переменные будут указывать на один и тот же объект.
Dim a As New Person() Dim b As Person = a ' Теперь a и b — ссылки на один и тот же объект
Можно ли использовать MemberwiseClone для глубокого копирования?
Ответ: Нет. Метод MemberwiseClone реализует только поверхностное копирование — все вложенные ссылочные типы копируются по ссылке.
Почему сериализация — не всегда универсальный способ глубокого копирования?
Ответ: Сериализация работает только с сериализуемыми объектами и может не поддерживать свойства с типом Object или не отмеченными как Serializable. Кроме этого, сериализация работает медленнее стандартного копирования.
Клиент копирует объект заказа оператором = для оформления нового заказа, не подозревая, что вложенный список позиций остался один на два объекта.
Плюсы: Быстро, просто
Минусы: Изменения в одном заказе меняют и другой — критические ошибки в учёте товаров.
Реализован метод DeepCopy для копирования заказа вместе со всеми вложенными товарами и адресом доставки.
Плюсы: Надежное разделение данных, корректная бизнес-логика
Минусы: Нужно внимательно следить за структурой объекта, больше кода для поддержки