Ви не повинні виходити з цього ICloneable.
Причина полягає в тому, що коли Microsoft розробляла рамку .net, вони ніколи не вказували, чи повинен Clone()метод ICloneableбути глибоким або дрібним клоном, таким чином інтерфейс семантично порушений, оскільки ваші абоненти не знають, чи буде виклик глибоким чи дрібним клонуванням об'єкта.
Натомість слід визначити власні IDeepCloneable(і IShallowCloneable) інтерфейси методами DeepClone()(і ShallowClone()).
Ви можете визначити два інтерфейси, один із загальним параметром для підтримки сильно набраного клонування та один без збереження слабо набраної здатності клонування, коли ви працюєте з колекціями різних типів об'єктів, що підлягають клонуванню:
public interface IDeepCloneable
{
object DeepClone();
}
public interface IDeepCloneable<T> : IDeepCloneable
{
T DeepClone();
}
Що б ви потім реалізували так:
public class SampleClass : IDeepCloneable<SampleClass>
{
public SampleClass DeepClone()
{
// Deep clone your object
return ...;
}
object IDeepCloneable.DeepClone()
{
return this.DeepClone();
}
}
Як правило, я віддаю перевагу використанню описаних інтерфейсів на відміну від конструктора копій, але це має чіткий намір. Конструктор копій, мабуть, вважатиметься глибоким клоном, але це, звичайно, не стільки чіткий намір, як використання інтерфейсу IDeepClonable.
Про це йдеться у .net Framework Design Design Guidelines та у блозі Бреда Абрамса
(Я думаю, якщо ви пишете заявку (на відміну від фреймворку / бібліотеки), тож ви можете бути впевнені, що ніхто за межами вашої команди не подзвонить ваш код, це не має великого значення, і ви можете призначити смислове значення "deepclone" інтерфейсу .net ICloneable, але ви повинні переконатися, що це добре задокументовано та добре зрозуміло у вашій команді. Особисто я б дотримувався рамкових рекомендацій.)