Зачем мне реализовывать ICloneable на c #?

111

Не могли бы вы объяснить мне, почему я должен унаследовать от метода ICloneableи реализовать его Clone()?

Если я хочу сделать глубокую копию, могу ли я просто реализовать свой метод? Скажем MyClone()?

Почему я должен наследовать от ICloneable? Каковы преимущества? Дело только в том, чтобы сделать код «более читабельным»?

uinc
источник

Ответы:

117

Вы не должны. Microsoft не рекомендует реализовывать, ICloneableпотому что в интерфейсе нет четкого указания, выполняет ли ваш Cloneметод «глубокий» или «неглубокий» клон.

См. Это сообщение в блоге Брэда Абрамса в 2003 году (!) Для получения дополнительной информации.

Мэтт Гамильтон
источник
4
Обратная ссылка на статью, которая сейчас 404: web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/…
harpo
2
Лучшая ссылка: blogs.msdn.microsoft.com/brada/2004/05/03/…
Эрик Липперт
29

ICloneableИнтерфейс сам по себе не очень полезно, что сказать , что на самом деле не так много ситуаций , когда это полезно знать , что объект является клонируемым , ничего не зная еще об этом. Это очень отличается от, например, IEnumerableили IDisposable; есть много ситуаций, когда полезно принять, IEnumerableне зная ничего, кроме как его перечислить.

С другой стороны, ICloneableможет быть полезно при применении в качестве общего ограничения наряду с другими ограничениями. Например, базовый класс может с пользой поддерживать ряд производных, некоторые из которых могут быть успешно клонированы, а некоторые - нет. Если бы базовый тип сам предоставлял общедоступный интерфейс клонирования, то любой производный тип, который не мог быть клонирован, нарушал бы принцип подстановки Лискова. Способ избежать этой проблемы состоит в том, чтобы обеспечить поддержку клонирования базового типа с помощью метода Protected и позволить производным типам реализовать общедоступный интерфейс клонирования по своему усмотрению.

Как только это будет выполнено, метод, который хочет принять объект WonderfulBaseтипа и должен иметь возможность клонировать его, может быть закодирован для принятия объекта WonderfulBase, который поддерживает клонирование (с использованием параметра универсального типа с базовым типом и ICloneableограничениями) . Хотя ICloneableинтерфейс сам по себе не будет указывать на глубокое или поверхностное клонирование, в документации для него WonderfulBaseбудет указано, WonderfulBaseдолжно ли клонироваться глубокое или поверхностное клонирование. По сути, ICloneableинтерфейс не будет выполнять ничего, чего нельзя было бы добиться путем определения ICloneableWonderfulBase, за исключением того, что он избегал бы определения разных имен для каждого отдельного клонируемого базового класса.

Supercat
источник
18

ICloneable- один из тех артефактов BCL, вызывающих споры. ИМХО, реальной причины для его реализации нет. С учетом сказанного, если я собираюсь создать метод клонирования, я реализую его ICloneableи предоставляю свою собственную строго типизированную версию Clone.

Проблема в ICloneableтом, что никогда не указывается, Cloneбыла ли это мелкая или глубокая копия, что очень разные вещи. Тот факт, что нет, ICloneable<T>может указывать на мысли Microsoft об ICloneable

JoshBerke
источник
9

Мэтт прав, не используйте его. Создайте свой собственный Copy()метод (или похожее имя) и четко укажите в своем общедоступном API, создает ли ваш метод глубокую или неглубокую копию вашего объекта.

Джон Раш
источник