Метод Object.MemberwiseClone делает поверхностную копию объекта, следуя некоторым очень простым правилам и используя преимущества работы .NET-сборщика мусора.
- Ссылки просто копируются. Это включает в себя строки и ссылки на любые
object
.
- Типы значений копируются битами (создаются идентичные клоны).
Часть о типах значений может быть легко продублирована с помощью Delphi. Дублирование поведения ссылочного типа с Delphi, хотя и технически легко, не даст ожидаемого результата: ожидается, что Delphi-код .free
создаст объекты, и использует парадигму owner-owned
, чтобы убедиться, что это происходит. Обычный шаблон - освободить объекты, созданные владельцем-объектом, от деструктора. Если вы сделаете копию объекта, это приведет к сбою. Вот пример:
- Объект A имеет ссылку на объект B.
- Мы создаем объект C как поверхностную копию объекта A. Теперь объект C содержит ссылку на объект B.
- Освобождаем объект A:
A.Free;
- Мы освобождаем объект B:
B.Free;
- это автоматически вызывает B.Free
, но, к сожалению, B был уже освобожден, когда мы освободили A!
Мы могли бы попытаться сделать deep-copy
, как предполагает Дэвид, но это создает некоторые не менее сложные проблемы:
- Не все объекты следует копировать, например, потому что они инкапсулируют ссылки на реальные ресурсы (например, TFileStream).
- Некоторые другие объекты не могут быть глубоко скопированы, потому что они находятся в эссессе Singletons. И нет универсального способа сказать: «Этот объект является Singleton, делайте простую справочную копию, не делайте глубокую копию». Пример: копируем ли мы
Application
?
- Если вы делаете глубокую копию, у вас могут быть циркулярные ссылки, вам нужно позаботиться об этом. Это не тривиально, и вы начинаете копирование с элемента в коллекции, вы можете оказаться обратно к родителю вашей коллекции, то есть: не совсем ожидаемый результат.
- Беспорядочное глубокое копирование может занять неожиданные объемы памяти и привести к неожиданным утечкам памяти. Подумайте еще раз о коллекции -> item -> copy item, где вы получите копию «item», но вся COLLECTION была скопирована из-за непредвиденных обратных ссылок.
Собрав все это вместе, мы можем прийти только к одному выводу: у нас не может быть общего назначения, Delphi-эквивалент MemberwiseClone
. Мы можем иметь частичное сходство для более простых объектов с несложными взаимодействиями, но это не так привлекательно!