Почему String.Empty не является константой?
В.Net почему String.Empty только для чтения вместо константы? Мне просто интересно, знает ли кто-нибудь, в чем причина этого решения.
4 ответа
Причина того, что static readonly
используется вместо const
должен использоваться с неуправляемым кодом, как указано Microsoft здесь, в общеязыковой версии 2.0 Shared Source. Файл для просмотра sscli20\clr\src\bcl\system\string.cs
,
Пустая константа содержит значение пустой строки. Нам нужно вызвать конструктор String, чтобы компилятор не помечал это как литерал.
Маркировка этого как литерала будет означать, что он не отображается как поле, к которому мы можем получить доступ из нативного.
Я нашел эту информацию из этой удобной статьи в CodeProject.
Я думаю, что здесь много путаницы и плохих ответов.
Прежде всего, const
поля static
члены (не члены экземпляра).
Проверьте раздел 10.4 Константы спецификации языка C#.
Несмотря на то, что константы считаются статическими членами, объявление константы не требует и не допускает статический модификатор.
Если public const
члены статичны, нельзя считать, что константа создаст новый объект.
Учитывая это, следующие строки кода делают то же самое в отношении создания нового объекта.
public static readonly string Empty = "";
public const string Empty = "";
Вот примечание от Microsoft, которое объясняет разницу между двумя:
Ключевое слово readonly отличается от ключевого слова const. Поле const может быть инициализировано только при объявлении поля. Поле только для чтения может быть инициализировано либо в объявлении, либо в конструкторе. Поэтому поля только для чтения могут иметь разные значения в зависимости от используемого конструктора. Кроме того, хотя поле const является константой времени компиляции, поле 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