Чому я повинен реалізувати ICloneable в c #?


110

Чи можете ви пояснити мені, чому мені слід успадковувати ICloneableта застосовувати Clone()метод?

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

Чому мені слід успадковувати ICloneable? Які переваги? Це лише питання про те, щоб зробити код "читабельнішим"?


Відповіді:


117

Ви не повинні. Microsoft рекомендує не застосовувати, ICloneableоскільки в інтерфейсі немає чітких показань, чи ваш Cloneметод виконує "глибокий" або "неглибокий" клон.

Дивіться цю публікацію в блозі від Бреда Абрамса ще в 2003 році (!) Для отримання додаткової інформації.


4
Зворотне посилання на статтю, якої зараз 404: web.archive.org/web/20040419170407/http://blogs.msdn.com/brada/…
harpo


29

ICloneableІнтерфейс сам по собі не дуже корисно, що сказати , що на насправді не так багато ситуацій , коли це корисно знати , що об'єкт є клонують , нічого не знаючи ще про це. Це дуже відрізняється від ситуації , наприклад , IEnumerableабо IDisposable; Є багато ситуацій, коли корисно прийняти знак, IEnumerableне знаючи нічого, крім того, як його перерахувати.

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

Як тільки це було досягнуто, метод, який хоче прийняти об'єкт WonderfulBaseтипу і потребує можливості його клонувати, може бути закодований, щоб прийняти об’єкт WonderfulBase, який підтримує клонування (використовуючи параметр загального типу з базовим типом та ICloneableобмеженнями) . Хоча ICloneableінтерфейс сам по собі не вказує на глибоке або неглибоке клонування, в документації на WonderfulBaseвказівку WonderfulBaseмає бути, чи повинен бути клонований глибокий або мілко клонований. По суті, ICloneableінтерфейс не виконає нічого, чого не вдасться виконати шляхом визначення ICloneableWonderfulBase, за винятком того, що це дозволить уникнути необхідності визначення різних імен для кожного різного базового класу, що можна клонувати.


18

ICloneableє одним із тих артефактів у БКЛ, які були суперечливими. Немає реальної причини ІМХО для його реалізації. З урахуванням сказаного, якщо я збираюся створити метод клонування, то я реалізую ICloneableі надаю власну сильну типізовану версію Clone.

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


9

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.