Почему я должен реализовать ICloneable в C#?
Можете ли вы объяснить мне, почему я должен наследовать от ICloneable
и реализовать Clone()
метод?
Если я хочу сделать глубокую копию, я не могу просто реализовать свой метод? Скажем MyClone()
?
Почему я должен наследовать от ICloneable
? Каковы преимущества? Это просто вопрос сделать код "более читабельным"?
4 ответа
Ты не должен. Microsoft рекомендует против реализации ICloneable
потому что нет четкого указания от интерфейса, является ли ваш Clone
Метод выполняет "глубокий" или "неглубокий" клон.
См. Этот пост в блоге от Брэда Абрамса в 2003 году (!) Для получения дополнительной информации.
ICloneable
интерфейс сам по себе не очень полезен, то есть не так уж много ситуаций, когда полезно знать, что объект является клонируемым, ничего не зная об этом. Это очень отличается от ситуации, например, IEnumerable
или же IDisposable
; Есть много ситуаций, когда полезно принять IEnumerable
не зная ничего, кроме как перечислить это.
С другой стороны, ICloneable
может быть полезно при применении в качестве общего ограничения вместе с другими ограничениями. Например, базовый класс может с пользой поддерживать ряд производных, некоторые из которых могут быть полезны для клонирования, а некоторые нет. Если сам базовый тип предоставляет открытый интерфейс клонирования, то любой производный тип, который не может быть клонирован, будет нарушать принцип подстановки Лискова. Чтобы избежать этой проблемы, нужно, чтобы базовый тип поддерживал клонирование с использованием защищенного метода и позволял производным типам реализовывать общедоступный интерфейс клонирования по своему усмотрению.
Как только это будет достигнуто, метод, который хочет принять объект WonderfulBase
type и должен иметь возможность клонировать его, может быть закодирован для принятия объекта WonderfulBase, который поддерживает клонирование (с использованием универсального параметра type с base-type и ICloneable
ограничения). Хотя ICloneable
сам интерфейс не будет указывать на глубокое или поверхностное клонирование, документация для WonderfulBase
будет указывать, является ли клонируемым WonderfulBase
должен быть глубоко или неглубоко клонирован. По сути, ICloneable
Интерфейс не будет выполнять ничего, что не будет достигнуто путем определения ICloneableWonderfulBase
за исключением того, что это позволит избежать необходимости определять разные имена для каждого другого клонируемого базового класса.
ICloneable
является одним из тех артефактов в BCL, который был спорным. ИМХО нет реальной причины для его реализации. С учетом сказанного, если я собираюсь создать метод клонирования, то я реализую ICloneable
и я предоставляю свою собственную строго типизированную версию Clone
,
Вопрос с ICloneable
это никогда не указано, если Clone
была мелкая или глубокая копия, которые очень разные вещи. Тот факт, что нет ICloneable<T>
может быть указанием на мысли Microsoft о ICloneable
Мэтт прав, не используйте его. Создайте свой собственный Copy()
метод (или аналогичное имя) и четко указывайте в вашем публичном API, создает ли ваш метод глубокую или неглубокую копию вашего объекта.