Ответы:
В .NET до версии 2.0 ""
создает объект, а string.Empty
объект ref не создает , что делает его string.Empty
более эффективным.
В версии 2.0 и более поздних версиях .NET все вхождения ""
ссылаются на один и тот же строковый литерал, что означает ""
эквивалент .Empty
, но все же не так быстро, как .Length == 0
.
.Length == 0
это самый быстрый вариант, но .Empty
делает код немного чище.
См. .NET спецификацию для получения дополнительной информации .
string.IsNullOrEmpty( stringVar )
.
в чем разница между 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
String.Empty
качестве аргумента в большинстве случаев. Вы правы, что все примеры показывают это, you simply can't put a (run-time) "value" into (compile-time) metadata
и это то, что примеры стремятся показать.
Предыдущие ответы были правильными для .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 сделает свое дело :)
String.Empty
поле только для чтения, в то время ""
как const . Это означает, что вы не можете использовать String.Empty
в операторе switch, потому что это не константа.
default
ключевого слова мы можем повысить удобочитаемость, предотвратить случайное изменение и иметь постоянную времени компиляции, хотя, если честно, я все еще думаю, что String.Empty более читабелен, чем по умолчанию, но медленнее
Другое отличие состоит в том, что 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
}
"bar " + (ok ? "" : "error")
Приведенные выше ответы являются технически правильными, но то, что вы действительно хотите использовать для лучшей читабельности кода и наименьшей вероятности исключения, - это String.IsNullOrEmpty (s)
--foo=$BAR
вы, вероятно, захотите заметить разницу между ними, забывшими установить env var, и с тем, чтобы они вообще не передавали флаг. string.IsNullOrEmpty
Это часто является запахом кода, который вы не проверили правильно, или делаете странные вещи. Вы не должны обычно принимать пустые строки, когда вы действительно хотите их использовать null
, или что-то вроде типа Maybe / Option.
Я склонен использовать, String.Empty
а не ""
по одной простой, но не очевидной причине:
""
и ""
это НЕ одно и то же, первый фактически содержит 16 символов нулевой ширины. Очевидно, что ни один компетентный разработчик не собирается добавлять символы нулевой ширины в свой код, но если они туда попадут, это может стать кошмаром обслуживания.
Ноты:
Я использовал U + FEFF в этом примере.
Не уверен, что SO будет есть эти символы, но попробуйте сами с одним из множества символов нулевой ширины.
Я только столкнулся с этим благодаря https://codegolf.stackexchange.com/
Используйте, String.Empty
а не ""
.
Это больше для скорости, чем использование памяти, но это полезный совет.
""
Является буквальным , так будет действовать как буквальным: на первом использовании оно создается и для следующих целей его ссылка возвращается. Только один экземпляр""
будет сохранен в памяти независимо от того, сколько раз мы его используем! Я не вижу здесь никаких штрафов за память. Проблема заключается в том, что каждый раз, когда""
используется, выполняется цикл сравнения, чтобы проверить, есть ли""
уже в пуле интернирования. С другой стороны,String.Empty
это ссылка на""
хранящуюся в зоне памяти .NET Framework .String.Empty
указывает на один и тот же адрес памяти для приложений VB.NET и C #. Так зачем искать ссылку каждый раз,""
когда вам нужно, когда у вас есть эта ссылка вString.Empty
?
Ссылка: String.Empty
против""
String.Empty не создает объект, тогда как "" создает. Однако разница, как указано здесь , тривиальна.
Все экземпляры "" являются одинаковыми интернированными строковыми литералами (или они должны быть). Таким образом, вы действительно не будете бросать новый объект в кучу каждый раз, когда используете «», а просто создаете ссылку на тот же самый интернированный объект. Сказав это, я предпочитаю строку. Пусто. Я думаю, что это делает код более читабельным.
Это просто не имеет значения!
Некоторое прошлое обсуждение этого:
http://www.codinghorror.com/blog/archives/000185.html
string mystring = "";
ldstr ""
ldstr
выдвигает новую ссылку на объект на строковый литерал, хранящийся в метаданных.
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
помещает значение статического поля в стек оценки
Я склонен использовать String.Empty
вместо, ""
потому что ИМХО это более понятно и меньше VB-иш.
Эрик Липперт писал (17 июня 2013 г.):
«Первым алгоритмом, над которым я работал в компиляторе C #, был оптимизатор, который обрабатывает конкатенации строк. К сожалению, мне не удалось перенести эти оптимизации в кодовую базу Roslyn до того, как я ушел; добраться до этого! "
Вот некоторые результаты Roslyn x64 по состоянию на январь 2019 года. Несмотря на консенсусные замечания других ответов на этой странице, мне не кажется, что текущий JIT x64 рассматривает все эти случаи одинаково, когда все сказано и сделано.
Тем не менее, обратите внимание, что только один из этих примеров на самом деле заканчивается вызовом String.Concat
, и я предполагаю, что это по неясным причинам правильности (в отличие от контроля за оптимизацией). Другие различия, кажется, труднее объяснить.
default (String) + {default (String), "", String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
"" + {default (String), "", String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty + {default (String), "", String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
Исходя из этого, с точки зрения Entity Framework: версии EF 6.1.3, по-видимому, обрабатывают String.Empty и "" по-разному при проверке.
string.Empty обрабатывается как нулевое значение для целей проверки и выдает ошибку проверки, если она используется в поле Обязательное (приписывается); где как "" пройдет валидацию и не выдаст ошибку.
Эта проблема может быть решена в EF 7+. Ссылка: - https://github.com/aspnet/EntityFramework/issues/2610 ).
Редактировать: [Обязательный (AllowEmptyStrings = true)] решит эту проблему, позволив string.Empty для проверки.
Поскольку String.Empty не является константой времени компиляции, вы не можете использовать ее в качестве значения по умолчанию в определении функции.
public void test(int i=0,string s="")
{
// Function Body
}
public void test(int i=0, string s=string.Empty) {}
не скомпилирует и скажет "Значение параметра по умолчанию для 's' должно быть константой времени компиляции. Ответ OP работает.
Когда вы визуально сканируете код, "" выглядит раскрашенным так, как раскрашиваются строки. string.Empty выглядит как обычный доступ к членам класса. Во время быстрого просмотра легче определить "" или интуитивно понять значение.
Определите строки (колоризация переполнения стека не совсем помогает, но в VS это более очевидно):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
\u00ad
.
Все здесь дали некоторые хорошие теоретические разъяснения. У меня было подобное сомнение. Поэтому я попробовал базовую кодировку на нем. И я нашел разницу. Вот в чем разница.
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
Таким образом, кажется, что «Null» означает абсолютно void, а «String.Empty» означает, что оно содержит какое-то значение, но оно пустое.
""
против string.Empty
. Только при попытке узнать, пуста ли строка, null
было упомянуто.
string.Empty
и каково было основание объявить этоreadonly
вместоconst
.