Почему String.Empty не является константой? - PullRequest
179 голосов
/ 03 февраля 2009

В .Net почему String.Empty только для чтения вместо константы? Мне просто интересно, знает ли кто-нибудь причину этого решения.

Ответы [ 4 ]

134 голосов
/ 03 февраля 2009

Причина использования static readonly вместо const заключается в использовании с неуправляемым кодом, как указано Microsoft здесь в общеязыковой общеязыковой инфраструктуре версии 2.0 Файл для просмотра sscli20\clr\src\bcl\system\string.cs.

Константа Empty содержит пустую строковое значение. Нам нужно позвонить Строковый конструктор, чтобы компилятор не помечает это как буквальный.

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

Я нашел эту информацию из этой удобной статьи на CodeProject .

23 голосов
/ 03 февраля 2009

Я думаю, что здесь много путаницы и плохих ответов.

Прежде всего, поля const являются static членами ( не членами экземпляра ).

Проверьте раздел 10.4 Константы спецификации языка C #.

Даже если константы считаются статические члены, константа-объявление не требует и не позволяет статический Модификатор.

Если public const члены являются статическими, нельзя считать, что константа создаст новый Объект.

Учитывая это, следующие строки кода делают точно то же самое в отношении создания нового объекта.

public static readonly string Empty = "";
public const string Empty = "";

Вот примечание от Microsoft, которое объясняет разницу между 2:

Ключевое слово только для чтения отличается от ключевое слово const. Константное поле может только инициализируется при объявлении поля. Поле только для чтения может быть инициализируется либо при объявлении или в конструкторе. Следовательно, Только для чтения поля могут иметь разные значения в зависимости от конструктора используемый. Кроме того, в то время как поле const является константа времени компиляции, только для чтения поле может быть использовано для выполнения константы, ...

Так что я считаю, что единственный правдоподобный ответ здесь - Джефф Йейтс.

4 голосов
/ 18 мая 2013
String.Empty read only instead of a constant?

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

Если оставить строку для чтения только в одном месте, как это String.Empty, программа сохранит одну и ту же строку только в одном месте и прочитает ее или обратится к ней - сохраняя минимум данных в памяти.

Также, если вы скомпилируете любую dll с использованием String.Empty в качестве const и по какой-либо причине измените String.Empty, то скомпилированная dll больше не будет работать так же, потому что cost делает внутренний код фактически сохраняйте копию строки при каждом вызове.

См. Этот код, например:

public class OneName
{
    const string cConst = "constant string";
    static string cStatic = "static string";
    readonly string cReadOnly = "read only string";

    protected void Fun()
    {
        string cAddThemAll ;

        cAddThemAll = cConst;
        cAddThemAll = cStatic ;
        cAddThemAll = cReadOnly;    
    }
}

придет компилятором как:

public class OneName
{
    // note that the const exist also here !
    private const string cConst = "constant string";
    private readonly string cReadOnly;
    private static string cStatic;

    static OneName()
    {
        cStatic = "static string";
    }

    public OneName()
    {
        this.cReadOnly = "read only string";
    }

    protected void Fun()
    {
        string cAddThemAll ;

        // look here, will replace the const string everywhere is finds it.
        cAddThemAll = "constant string";
        cAddThemAll = cStatic;
        // but the read only will only get it from "one place".
        cAddThemAll = this.cReadOnly;

    }
}

и сборка вызова

        cAddThemAll = cConst;
0000003e  mov         eax,dword ptr ds:[09379C0Ch] 
00000044  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cStatic ;
00000047  mov         eax,dword ptr ds:[094E8C44h] 
0000004c  mov         dword ptr [ebp-44h],eax 
        cAddThemAll = cReadOnly;
0000004f  mov         eax,dword ptr [ebp-3Ch] 
00000052  mov         eax,dword ptr [eax+0000017Ch] 
00000058  mov         dword ptr [ebp-44h],eax 

Редактировать: Исправлена ​​опечатка

0 голосов
/ 03 февраля 2009

Этот ответ существует для исторических целей.

Первоначально:

Поскольку String является классом и поэтому не может быть константой.

Расширенное обсуждение:

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

В .NET (в отличие от Java) строка и строка в точности совпадают. И да, вы можете иметь строковые литеральные константы в .NET - DrJokepu 3 февраля 2009 г. в 16: 57

Вы говорите, что у класса не может быть констант? - StingyJack, 3 февраля 2009 г., 16: 58

Да, объекты должны использоваться только для чтения. Только структуры могут делать константы. Я думаю, что когда вы используете string вместо String, компилятор превращает const в readonly для вас. Все, что нужно сделать, чтобы программисты на C были довольны. - Гарри Шатлер 3 февраля 2009 года в 16: 59

tvanfosson только что объяснил это немного более многословно. «X не может быть константой, потому что содержащий Y является классом» было слишком мало контекстно-зависимым;) - Леонидас 3 февраля 2009 г. в 17: 01

string.Empty - это статическое свойство, которое возвращает экземпляр класса String, а именно пустую строку, а не сам класс строки. - tvanfosson 3 февраля 2009 г. в 17:00

Empty - это доступный только для чтения экземпляр (это не свойство) класса String. - Senfo 3 февраля 2009 г., 17: 02

Голова болит. Я все еще думаю, что я прав, но теперь я менее уверен. Исследование требуется сегодня вечером! - Гарри Шатлер 3 февраля 2009 года в 17: 07

Пустая строка является экземпляром класса string. Пустое - это статическое поле (я не исправляю это свойство) в классе String. В основном разница между указателем и тем, на что он указывает. Если бы это было не только для чтения, мы могли бы изменить, к какому экземпляру относится поле Empty. - tvanfosson 3 февраля 2009 года в 17: 07

Гарри, тебе не нужно проводить никаких исследований. Думаю об этом. Строка это класс. Пустой является экземпляром строки. - Senfo 3 февраля 2009 г., 17: 12

Есть кое-что, чего я не совсем понимаю: как статический конструктор класса String может создать экземпляр класса String? Разве это не какой-то сценарий "курица или яйцо"? - DrJokepu 3 февраля 2009 года в 17:12 5

Этот ответ будет правильным для почти любого другого класса, кроме System.String. В .NET много специальных возможностей для обработки строк, и одна из них заключается в том, что вы МОЖЕТЕ иметь строковые константы, просто попробуйте. В этом случае Джефф Йейтс имеет правильный ответ. - Джоэл Мюллер 3 февраля 2009 года в 19: 25

Как описано в §7.18, константное выражение - это выражение, которое может быть полностью оценено во время компиляции. Поскольку единственный способ создать ненулевое значение ссылочного типа, отличного от строки, это применить оператор new, а поскольку новый оператор не разрешен в выражении константы, единственно возможное значение для констант ссылочных типов кроме строки ноль. Предыдущие два комментария были взяты непосредственно из спецификации языка C # и повторяют то, что упоминал Джоэл Мюллер. - Senfo 4 февраля 2009 в 15:05 5

...