В C#, почему Строка является ссылочным типом, который ведет себя как тип значения?

Это должно делать то, что вы хотите. Он использует std::reference_wrapper так, как это было задумано (передача ссылок таким способом, который делает их копируемыми и назначаемыми). Я не вижу в этом ничего плохого. Из cppreference.com :

std :: reference_wrapper - это шаблон класса, который оборачивает ссылку в копируемый, назначаемый объект. Он часто используется как механизм для хранения ссылок внутри стандартных контейнеров (например, std :: vector), которые обычно не могут содержать ссылки.

blockquote>

Единственный потенциальный недостаток, который я вижу, это то, что std::reference_wrapper может быть немного неудобным для использования и незнакомым для некоторых. Более распространенным решением вашей проблемы, вероятно, было бы просто сохранить указатель в вашем объекте вместо ссылки. Например:

class T {
private:
    const U* _u;

public:
    T(const U& u)
        : _u(&u) {}
    …
};

348
задан codekaizen 25 June 2010 в 04:30
поделиться

7 ответов

Строки не являются типами значения, так как они могут быть огромными, и должны быть сохранены на "куче". Типы значения (во всех реализациях CLR на данный момент) сохранены на стеке. Строки выделения стека повредили бы все виды вещей: стек составляет только 1 МБ для 32-разрядного и 4 МБ для 64-разрядного, необходимо было бы упаковать каждую строку, подвергнувшись штрафу копии, Вы не могли интернировать строки, и использование памяти увеличится, и т.д.

(Редактирование: Добавленное разъяснение о значении вводит устройство хранения данных, являющееся деталью реализации, которая приводит к этой ситуации, где у нас есть тип со значением sematics не наследовавшийся Системе. ValueType. Спасибо Ben.)

315
ответ дан Dave Black 23 November 2019 в 00:28
поделиться

То, как можно сказать string, является ссылочным типом? Я не уверен, что имеет значение, как это реализовано. Строки в C# неизменны точно так, чтобы Вы не волновались об этой проблеме.

2
ответ дан 23 November 2019 в 00:28
поделиться

Это - главным образом проблема производительности.

строки Наличия ведут себя КАК тип значения, помогает, когда написание кода, но наличие его БЫТЬ типом значения сделало бы огромный хит производительности.

Для всестороннего взгляда, посмотрите на хорошая статья о строках в платформе .NET.

5
ответ дан Denis Troller 23 November 2019 в 00:28
поделиться

На самом деле строки имеют очень немного подобий для оценки типов. Для начала, не все типы значения неизменны, можно изменить значение Int32 все, что Вы хотите, и это это все еще был бы тот же адрес на стеке.

Строки неизменны на очень серьезном основании, оно не имеет никакого отношения к нему являющийся ссылочным типом, но имеет непосредственное отношение к управлению памятью. Просто более эффективно создать новый объект когда изменения размера строки, чем сместить вещи вокруг на управляемой "куче". Я думаю, что Вы смешиваете значение/ссылочные типы и неизменные понятия объектов.

До "==": Как Вы сказал "==", перегрузка оператора, и снова она была реализована на очень серьезном основании сделать платформу более полезной при работе со строками.

2
ответ дан Adam 23 November 2019 в 00:28
поделиться

Это не тип значения потому что производительность (пространство и время!) было бы ужасно, если бы это был тип значения, и его значение должно было быть скопировано каждый раз, когда это было передано и возвратилось из методов, и т.д.

Это имеет семантику значения для хранения мира нормальным. Можно ли вообразить, как трудный это должно было бы кодировать, если

string s = "hello";
string t = "hello";
bool b = (s == t);

устанавливает b, чтобы быть false? Вообразите, как трудное кодирование примерно любое приложение было бы.

55
ответ дан jason 23 November 2019 в 00:28
поделиться

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

, Возможно, Jon Skeet может помочь встать здесь?

6
ответ дан Chris 23 November 2019 в 00:28
поделиться

Не только строки являются неизменяемыми ссылочными типами. Многоабонентские делегаты тоже. Вот почему писать

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

безопасно. Я полагаю, что строки неизменяемы, потому что это наиболее безопасный метод работы с ними и выделения памяти. Почему они не являются типами значений? Предыдущие авторы правы в отношении размера стека и т. Д. Я бы также добавил, что создание строк ссылочными типами позволяет сэкономить на размере сборки, когда вы используете одну и ту же постоянную строку в программе. Если вы определите

string s1 = "my string";
//some code here
string s2 = "my string";

, скорее всего, оба экземпляра константы «моя строка» будут размещены в вашей сборке только один раз.

Если вы хотите управлять строками как обычным ссылочным типом, поместите строку в новый StringBuilder (string s). Или используйте MemoryStreams.

Если вы хотите создать библиотеку, в которой вы ожидаете, что в ваши функции будут передаваться огромные строки, определите параметр как StringBuilder или как Stream.

8
ответ дан 23 November 2019 в 00:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: