Почему String.Clone() возвращает исходную строку, а не ее копию?
Удивительно, String.Clone()
не возвращает копию строки как String.Copy()
сделал бы. Вместо этого он возвращает 'this'
оригинальная строка.
Я хотел бы понять, почему команда.Net Framework решила пойти по этому пути.
Согласно MSDN:
Интерфейс ICloneable [...] требует, чтобы ваша реализация метода Clone возвращала копию текущего экземпляра объекта.
String.Clone()
явно не следует этому руководству.
Я знаю, что строки неизменяемы, но если здесь была причина неизменности, String.Copy()
также вернется this
но это не так.
Это довольно теоретический вопрос, конечно.
3 ответа
Как вы могли обнаружить разницу? Только сравнивая две ссылки, используя object.ReferenceEquals
, Но с помощью любой семантической операции над строкой вы не сможете увидеть разницу.
Сравнение строк по ссылке почти всегда является ошибкой для начала, потому что вы редко можете рассчитывать на интернирование, чтобы это произошло или не произойдет.
Эта проблема касается не только String
, Если бы у вас был неизменный Point
класс, почему вы должны вернуть свежий объект из Clone
? Незачем.
IClonable
во всяком случае, редко используется и редко полезен. Если вы хотите показать пользователям вашего класса способ получить копию данного экземпляра, вам не нужно наследовать от IClonable
совсем.
IClonable несколько устарел, так как неясно, что означает "клон" с общесистемной точки зрения (глубокий, неглубокий...). См. http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx
Ссылочный источник документирует метод Clone со следующим комментарием:
// Нет смысла клонировать строку, поскольку она неизменна, поэтому мы просто возвращаем это.
Интернирование строк означает, что сбор строк затруднен (на них можно ссылаться более одного раза), что означает, что создание новой копии строки служит только для нагрузки системы. Кроме того, интернирование и копирование конфликтуют друг с другом - так что общее правило интернирования выигрывает.
Как уже упоминалось, поскольку строки доступны только для чтения, Clone() ведет себя разумно. Фактически вам никогда не нужны два отдельных экземпляра строки, и, не делая копию, память сохраняется. В очень редком случае, когда вам действительно нужна копия (по какой-то причине вы хотите Object.ReferenceEquals
возвращать false
), ты можешь использовать String.Copy()
вместо.
Может показаться бессмысленным иметь метод, который просто возвращает this
, Причиной использования такого метода является реализация ICloneable
и я согласен, что String
следует реализовать ICloneable
так что общий код, как
T Foo<T>(T x, ...) where T:ICloneable {/* code that might clone x*/}
может быть совместим с String.
Мне немного странно, что метод public
тем не менее, поскольку нет причин называть это напрямую. Это имело бы смысл, если бы оно было доступно только через ссылку на ICloneable
,