Nie powinieneś pochodzić z ICloneable.
Powodem jest to, że kiedy Microsoft zaprojektował framework .net nigdy nie określił, czy Clone()metoda ICloneablepowinna być głębokim, czy płytkim klonem, więc interfejs jest semantycznie zepsuty, ponieważ wywołujący nie będą wiedzieć, czy wywołanie będzie głęboko, czy płytko sklonuje obiekt.
Zamiast tego powinieneś zdefiniować własne IDeepCloneable(i IShallowCloneable) interfejsy z metodami DeepClone()(i ShallowClone()).
Można zdefiniować dwa interfejsy, jeden z parametrem ogólnym obsługującym klonowanie silnie wpisane, a drugi bez zachowania możliwości klonowania słabo typizowanego podczas pracy z kolekcjami różnych typów obiektów, które można klonować:
public interface IDeepCloneable
{
object DeepClone();
}
public interface IDeepCloneable<T> : IDeepCloneable
{
T DeepClone();
}
Które następnie zaimplementowałbyś w ten sposób:
public class SampleClass : IDeepCloneable<SampleClass>
{
public SampleClass DeepClone()
{
// Deep clone your object
return ...;
}
object IDeepCloneable.DeepClone()
{
return this.DeepClone();
}
}
Generalnie wolę używać opisanych interfejsów w przeciwieństwie do konstruktora kopiującego, dzięki czemu cel jest bardzo jasny. Prawdopodobnie zakłada się, że konstruktor kopiujący jest głębokim klonem, ale z pewnością nie jest to tak wyraźny zamiar, jak użycie interfejsu IDeepClonable.
Jest to omówione w wytycznych dotyczących projektowania frameworka .net oraz na blogu Brada Abramsa
(Przypuszczam, że jeśli piszesz aplikację (w przeciwieństwie do frameworka / biblioteki), więc możesz być pewien, że nikt spoza Twojego zespołu nie będzie wywoływał Twojego kodu, nie ma to większego znaczenia i możesz przypisać znaczenie semantyczne "deepclone" do interfejsu .net ICloneable, ale powinieneś upewnić się, że jest to dobrze udokumentowane i dobrze zrozumiane w Twoim zespole. Osobiście trzymałbym się wytycznych dotyczących frameworka).