Почему не String.Empty константа?

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Несмотря на то, что считаются константы статические члены, декларация констант ни требует, ни статического Модификатор.

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

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

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

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

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

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

Ответ 3

String.Empty read only instead of a constant?

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

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

Также, если вы скомпилируете любую dll с помощью String.Empty as 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 

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

Ответ 4

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

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

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

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

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

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

Вы говорите, что класс не может иметь константы? - StingyJack

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

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

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

Пусто - это экземпляр readonly (это не свойство) класса String. - senfo 3 февраля 2009 в 17:02

Голова болит. Я все еще думаю, что я прав, но теперь я менее уверен. Исследования нужны сегодня! #: 3459 Garry Shutler

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

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

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

Этот ответ будет правильным для любого другого класса, но System.String..NET делает очень много специальных функций для строк, и один из них состоит в том, что вы можете иметь строковые константы, просто попробуйте. В этом случае Джефф Йейтс имеет правильный ответ. #: 3059 Joel Mueller

Как описано в §7.18, константное выражение является выражением, которое может быть полностью оценено во время компиляции. Поскольку единственным способом создания ненулевого значения ссылочного типа, отличного от строки, является применение нового оператора, и поскольку новый оператор не допускается в константном выражении, единственное возможное значение для констант ссылочных типов кроме строки, равно null. Предыдущие два комментария были взяты непосредственно из спецификации языка С# и повторили то, что упоминал Джоэл Мюллер. #: 3159 senfo senfo в 15:05 5