Подтвердить что ты не робот

Почему String.Clone() возвращает исходную строку, а не ее копию?

Удивительно, что String.Clone() не возвращает копию строки, которую будет выполнять String.Copy(). Вместо этого он возвращает 'this', исходную строку.

Я хотел бы понять, почему команда .Net Framework решила пойти таким образом.

По MSDN:

Интерфейс ICloneable [...] требует, чтобы ваша реализация метод Clone возвращает копию текущего экземпляра объекта.

String.Clone() ясно не соответствует этому руководству.

Я знаю, что строки неизменяемы, но если неизменность была причиной здесь, String.Copy() также вернул бы this, но это не так.

Это, конечно, довольно теоретический вопрос.

4b9b3361

Ответ 1

Как вы могли обнаружить разницу? Только путем сравнения двух ссылок с помощью object.ReferenceEquals. Но любой семантической операцией на строке вы не можете отличить.

Сравнение строк по ссылке почти всегда является ошибкой, потому что вы редко можете полагаться на интернирование, чтобы случиться или не произошло.

Эта проблема относится не только к String. Если у вас был неизменный класс Point, почему бы вам вернуть новый объект из Clone? Нет необходимости.

IClonable редко используется и редко используется, во всяком случае. Если вы хотите показать пользователям своего класса способ получить копию данного экземпляра, вам вообще не нужно наследовать от IClonable.

Ответ 2

IClonable несколько устарел, поскольку неясно, что означает "Клон" с общесистемной точки зрения (глубокая, мелкая...). См. http://blogs.msdn.com/b/brada/archive/2003/04/09/49935.aspx

Источник ссылки документирует метод Clone со следующим комментарием:

//Нет смысла клонировать строку, поскольку они неизменяемы, поэтому мы просто возвращаем это.

Интернирование строк означает, что трудно собрать строки (на них можно ссылаться более одного раза), что означает, что действительно создание новой копии строки служит только для того, чтобы подчеркнуть систему. Кроме того, интернирование и копирование конфликтуют друг с другом, поэтому выигрывает общее правило интернирования.

Ответ 3

Как уже упоминалось, поскольку строки доступны только для чтения, Clone() ведет себя разумно. Фактически вам фактически не нужны два отдельных экземпляра строки, и, не делая копии, память сохраняется. В очень редком случае, когда вам действительно нужна копия (по какой-то причине вы хотите вернуть Object.ReferenceEquals false), вы можете вместо этого использовать String.Copy().

Может показаться бессмысленным иметь метод, который просто возвращает this. Причиной такого метода является реализация ICloneable, и я согласен, что String должен реализовать ICloneable так, чтобы общий код, например

T Foo<T>(T x, ...) where T:ICloneable {/* code that might clone x*/}

может быть совместим со строкой.

Немного странно, что метод public, хотя нет причин для его прямого вызова. Было бы разумно, если бы доступно только через ссылку на ICloneable.