В чем разница между String.Empty и "" (пустая строка)? - PullRequest
272 голосов
/ 30 сентября 2008

В .NET, в чем разница между String.Empty и "", и являются ли они взаимозаменяемыми, или есть какие-то базовые проблемы с ссылками или локализацией вокруг равенства, которые String.Empty обеспечит, что это не проблема?

Ответы [ 17 ]

277 голосов
/ 30 сентября 2008

В .NET до версии 2.0 "" создает объект, а string.Empty не создает объект ref , что делает string.Empty более эффективным.

В версии 2.0 и более поздних версиях .NET все вхождения "" ссылаются на один и тот же строковый литерал, что означает, что "" эквивалентен .Empty, но все же не так быстро, как .Length == 0.

.Length == 0 - самый быстрый вариант, но .Empty делает код немного чище.

Дополнительную информацию см. В спецификации .NET .

.
181 голосов
/ 04 декабря 2012

В чем разница между String.Empty и "", и являются ли они взаимозаменяемы

string.Empty - поле только для чтения, тогда как "" - постоянная времени компиляции. Места, где они ведут себя по-разному:

Значение параметра по умолчанию в C # 4.0 или выше

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
    //... implementation
}

Выражение регистра в выражении switch

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}

Аргументы атрибутов

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type
38 голосов
/ 30 сентября 2008

Предыдущие ответы были правильными для .NET 1.1 (посмотрите дату поста, на который они ссылались: 2003). Начиная с .NET 2.0 и более поздних версий, по сути, нет никакой разницы. JIT все равно будет ссылаться на один и тот же объект в куче.

В соответствии со спецификацией C #, раздел 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

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

Кто-то даже упоминает об этом в комментариях к посту Брэда Абрама

Таким образом, практический результат "" против String.Empty равен нулю. JIT выяснит это в конце.

Лично я обнаружил, что JIT намного умнее меня, и поэтому я стараюсь не слишком умничать с такими оптимизациями микрокомпилятора. JIT развернется для циклов (), удалит избыточный код, встроенные методы и т. Д. Лучше и в более подходящее время, чем когда-либо мог ожидать компилятор I или C #. Пусть JIT сделает свое дело:)

35 голосов
/ 01 октября 2008

String.Empty - это поле только для чтения , а "" - это const . Это означает, что вы не можете использовать String.Empty в операторе switch, поскольку он не является константой.

18 голосов
/ 30 июня 2013

Другое отличие состоит в том, что String.Empty генерирует больший код CIL. Хотя код для ссылки "" и String.Empty имеет одинаковую длину, компилятор не оптимизирует конкатенацию строк (см. сообщение в блоге Эрика Липперта ) для аргументов String.Empty. Следующие эквивалентные функции

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}

создать этот IL

.method private hidebysig instance string foo() cil managed
{
    .maxstack 8
    L_0000: ldstr "foo"
    L_0005: ret 
}
.method private hidebysig instance string bar() cil managed
{
    .maxstack 8
    L_0000: ldstr "bar"
    L_0005: ldsfld string [mscorlib]System.String::Empty
    L_000a: call string [mscorlib]System.String::Concat(string, string)
    L_000f: ret 
}
13 голосов
/ 30 сентября 2008

Приведенные выше ответы технически правильны, но то, что вы действительно хотите использовать, для лучшей читаемости кода и наименьшей вероятности исключения - String.IsNullOrEmpty (s)

8 голосов
/ 11 февраля 2016

Используйте String.Empty вместо "".

Это больше для скорости, чем для использования памяти, но это полезный совет. "" - это литерал, поэтому он будет действовать как литерал: при первом использовании он создан и для последующего использования возвращается его ссылка. Только один экземпляр "" будет храниться в памяти независимо от того, сколько раз мы используй это! Я не вижу здесь никаких штрафов за память. Проблема в том, что каждый раз, когда используется "", выполняется цикл сравнения, чтобы проверить, "" уже находится во внутреннем пуле. С другой стороны, String.Empty является ссылкой на "", хранящуюся в зоне памяти .NET Framework . String.Empty указывает на один и тот же адрес памяти для VB.NET и C # Приложения. Так зачем искать ссылку каждый раз, когда вам нужно "" когда у вас есть эта ссылка в String.Empty?

Ссылка: String.Empty против ""

7 голосов
/ 25 ноября 2015

Я склонен использовать String.Empty вместо "" по одной простой, но не очевидной причине: "" и "" НЕ одинаковы, первый фактически содержит 16 символов нулевой ширины. Очевидно, что ни один компетентный разработчик не собирается добавлять символы нулевой ширины в свой код, но если они туда попадут, это может стать кошмаром обслуживания.

Примечания:

  • Я использовал U + FEFF в этом примере.

  • Не уверен, что SO будет есть эти символы, но попробуйте сами с одним из множества символов нулевой ширины

  • Я только столкнулся с этим благодаря https://codegolf.stackexchange.com/

7 голосов
/ 30 сентября 2008

String.Empty не создает объект, тогда как "" создает. Однако, как указано здесь , разница незначительна.

6 голосов
/ 30 сентября 2008

Это просто не имеет значения!

Некоторые прошлые обсуждения этого:

http://www.codinghorror.com/blog/archives/000185.html

http://blogs.msdn.com/brada/archive/2003/04/22/49997.aspx

http://blogs.msdn.com/brada/archive/2003/04/27/50014.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...