В .NET почему String.Empty
только для чтения вместо константы? Мне просто интересно, знает ли кто-нибудь, по какой причине было принято это решение.
Почему String.Empty не является константой?
Ответы (4)
Причина, по которой static readonly
используется вместо const
, связана с использованием с неуправляемым кодом, как указано Microsoft здесь в Версия 2.0 инфраструктуры общего языка с общим исходным кодом. Файл для просмотра - sscli20\clr\src\bcl\system\string.cs
.
Константа Empty содержит значение пустой строки. Нам нужно вызвать конструктор String, чтобы компилятор не пометил это как литерал.
Пометка его как буквального означает, что оно не отображается как поле, к которому мы можем получить доступ из родного.
Я нашел эту информацию в этой удобной статье на CodeProject.
String.Empty
только по этой причине.
- person julealgon; 04.08.2014
Я думаю, здесь много путаницы и плохих отзывов.
Прежде всего, const
поля являются static
членами (не членами экземпляра).
См. Раздел 10.4 Константы спецификации языка C #.
Несмотря на то, что константы считаются статическими членами, объявление константы не требует и не допускает модификатора static.
Если 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
, на нее была бы сделана ссылка, и ее значение было бы определено во время выполнения.
- person Jeff Yates; 16.08.2012
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 03 фев.
Вы хотите сказать, что у класса не может быть констант? - StingyJack 3 фев.
Да, объекты должны использоваться только для чтения. Только структуры могут создавать константы. Я думаю, что когда вы используете
string
вместоString
, компилятор меняет const на readonly для вас. Все для того, чтобы сделать программистов на C счастливыми. - Гарри Шатлер, 03 фев. 2009, 16:59tvanfosson просто объяснил это более подробно. «X не может быть константой, потому что содержащий Y класс» было слишком контекстно-зависимым;) - Леонидас 3 фев. 2009 в 17:01
string.Empty - это статическое свойство, которое возвращает экземпляр класса String, а именно пустую строку, а не сам класс строки. - tvanfosson 3 фев.
Empty - это экземпляр класса String, доступный только для чтения (это не свойство). - senfo 03 фев.
Голова болит. Я все еще думаю, что прав, но теперь я менее уверен. Сегодня вечером требуется исследование! - Гарри Шатлер, 3 февраля 2009 г., 17:07
Пустая строка - это экземпляр класса строки. Empty - это статическое поле (не свойство, я поправляюсь) в классе String. В основном разница между указателем и тем, на что он указывает. Если бы это было не только для чтения, мы могли бы изменить, к какому экземпляру относится пустое поле. - tvanfosson 3 фев.
Гарри, тебе не нужно проводить никаких исследований. Думаю об этом. Строка - это класс. Empty - это экземпляр String. - senfo 03 фев. 2009 в 17:12
Есть кое-что, чего я не совсем понимаю: как вообще статический конструктор класса String может создать экземпляр класса String? Разве это не сценарий «курица или яйцо»? - DrJokepu 3 фев.
Этот ответ будет правильным почти для любого другого класса, кроме System.String. .NET делает много работы с особенным регистром для строк, и одна из них заключается в том, что вы МОЖЕТЕ иметь строковые константы, просто попробуйте. В этом случае Джефф Йейтс знает правильный ответ. - Джоэл Мюллер 3 фев.
Как описано в §7.18, константное выражение - это выражение, которое может быть полностью вычислено во время компиляции. Поскольку единственный способ создать ненулевое значение ссылочного типа, отличного от строки, - это применить новый оператор, и поскольку новый оператор не разрешен в константном выражении, единственное возможное значение для констант ссылочных типов кроме строки является нулем. Предыдущие два комментария были взяты непосредственно из спецификации языка C # и повторяют то, что упомянул Джоэл Мюллер. - senfo 4 фев.