Почему я должен реализовать ICloneable в C #? - PullRequest
108 голосов
/ 31 марта 2009

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

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

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

Ответы [ 4 ]

116 голосов
/ 31 марта 2009

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

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

28 голосов
/ 15 ноября 2010

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

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

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

18 голосов
/ 31 марта 2009

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

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

9 голосов
/ 31 марта 2009

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

...