В .Net почему String.Empty только для чтения вместо константы? Мне просто интересно, знает ли кто-нибудь, в чем причина этого решения.
В .Net почему String.Empty только для чтения вместо константы? Мне просто интересно, знает ли кто-нибудь, в чем причина этого решения.
Ответы:
Причина, по static readonly
которой вместо этого const
происходит, связана с использованием неуправляемого кода, как указано Microsoft здесь, в общеязыковой версии 2.0 Shared Source . Файл для просмотра есть sscli20\clr\src\bcl\system\string.cs
.
Пустая константа содержит значение пустой строки. Нам нужно вызвать конструктор String, чтобы компилятор не помечал это как литерал.
Маркировка этого как литерала будет означать, что он не отображается как поле, к которому мы можем получить доступ из нативного.
Я нашел эту информацию из этой удобной статьи в CodeProject .
String.Empty
больше по этой причине в одиночку.
Я думаю, что здесь много путаницы и плохих ответов.
Прежде всего, const
поля являются static
членами ( не членами экземпляра) ).
Проверьте раздел 10.4 Константы спецификации языка C #.
Даже если константы считаются статическими членами, объявление константы не требует и не допускает статический модификатор.
Если public const
члены являются статическими, нельзя считать, что константа создаст новый объект.
Учитывая это, следующие строки кода делают абсолютно то же самое в отношении создания нового объекта.
public static readonly string Empty = "";
public const string Empty = "";
Вот примечание от Microsoft, которое объясняет разницу между двумя:
Ключевое слово readonly отличается от ключевого слова const. Поле const может быть инициализировано только при объявлении поля. Поле только для чтения может быть инициализировано либо в объявлении, либо в конструкторе. Поэтому поля только для чтения могут иметь разные значения в зависимости от используемого конструктора. Кроме того, хотя поле const является константой времени компиляции, поле readonly может использоваться для констант времени выполнения, ...
Поэтому я считаю, что единственный правдоподобный ответ здесь - это Джефф Йейтс.
const string
и static readonly string
делаю то же самое. Const-значения подставляются в связанный код, тогда как статические значения доступны только для чтения. Если у вас есть const
библиотека A, которая используется библиотекой B, библиотека B заменит все ссылки на эту const
переменную ее литеральным значением; если бы эта переменная была static readonly
взамен, на нее будет ссылаться и ее значение будет определено во время выполнения.
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
Редактировать: Исправлена опечатка
Этот ответ существует в исторических целях.
Первоначально:
Потому String
что это класс и, следовательно, не может быть константой.
Расширенное обсуждение:
При проверке этого ответа было разработано множество полезных диалогов, и вместо того, чтобы удалять его, этот контент воспроизводится напрямую:
В .NET (в отличие от Java) строка и строка в точности совпадают. И да, вы можете иметь строковые литеральные константы в .NET - DrJokepu 3 февраля 2009 г. в 16:57
Вы говорите, что у класса не может быть констант? - StingyJack 3 февраля 2009 в 16:58
Да, объекты должны использовать только для чтения. Только структуры могут делать константы. Я думаю, что когда вы используете
string
вместоString
компилятора, const превращается в readonly для вас. Все, что нужно сделать, чтобы программисты на C были довольны. - Гарри Шатлер 3 февраля 2009 года в 16:59Тванфоссон только что объяснил это более многословно. «X не может быть константой, потому что содержащий Y является классом» было слишком мало контекстно-зависимым;) - Leonidas 3 февраля 2009 г. в 17:01
string.Empty - это статическое свойство, которое возвращает экземпляр класса String, а именно пустую строку, а не сам класс строки. - tvanfosson 3 февраля 2009 г. в 17:01
Empty - это доступный только для чтения экземпляр (это не свойство) класса String. - Senfo 3 февраля 2009 в 17:02
Голова болит. Я все еще думаю, что я прав, но теперь я менее уверен. Исследование требуется сегодня вечером! - Гарри Шатлер 3 февраля 2009 года в 17:07
Пустая строка является экземпляром класса string. Пустое - это статическое поле (я не исправляю это свойство) в классе String. В основном разница между указателем и тем, на что он указывает. Если бы это было не только для чтения, мы могли бы изменить, к какому экземпляру относится пустое поле. - 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