2009-03-30 2 views
106

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

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

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

+0

** См. Также **: [ICloneable Controversy: должен ли класс реализовывать ICloneable или нет?] (Http://www.sysexpand.com/?path=howto/implement-icloneable-or-not) – KyleMit

ответ

111

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

См. this blog post from Brad Abrams еще в 2003 году (!) Для получения дополнительной информации.

+4

Wayback ссылка на статью, которая сейчас составляет 404: http://web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/archive/2003/04/09/49935.aspx – harpo

+1

Лучшая ссылка : https://blogs.msdn.microsoft.com/brada/2004/05/03/should-we-obsolete-icloneable-the-slar-on-system-icloneable/ –

18

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

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

9

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

27

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

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

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

+3

+1 для принципа Лискова – TheSilverBullet

Смежные вопросы