В C # я должен использовать string.Empty или String.Empty или «» для инициализации строки?


705

В C # я хочу инициализировать строковое значение пустой строкой.

Как мне это сделать? Каков правильный путь и почему?

string willi = string.Empty;

или

string willi = String.Empty;

или

string willi = "";

или что?


7
См. Также подобное обсуждение для java: stackoverflow.com/questions/213985/…
harpo

39
хотя лучше использовать String.IsNullOrEmpty (строка myString)?
ZombieSheep

3
Я использую [string.IsNullOrWhiteSpace (stringvalue)] ... работает в .Net 4.0. Для инициализации я просто использую: [var text = "";] Простой, читаемый и набирает меньше времени :)
Джалал Эль-Шаер

61
Что более важно, это смешное имя вашей переменной.
Ардж

5
Что меня заинтересовало, так это то, почему есть даже свойство Empty. Это приятно и все, но не обязательно и не обязательно.
MasterMastic

Ответы:


808

Используйте то, что вы и ваша команда считаете наиболее читабельным.

Другие ответы предполагают, что новая строка создается каждый раз, когда вы используете "" . Это не так - из-за интернирования строк он будет создаваться либо один раз для сборки, либо один раз для домена приложения (или, возможно, один раз для всего процесса - не уверен на этом фронте). Эта разница незначительна - в широком масштабе, массово незначительна.

Однако то, что вы находите более читабельным, - это другое дело. Это субъективно и будет варьироваться от человека к человеку - поэтому я предлагаю вам узнать, что нравится большинству людей в вашей команде, и все согласны с этим. Лично мне ""легче читать.

Аргумент, что ""и " "их легко принять друг за друга, на самом деле меня не касается. Если вы не используете пропорциональный шрифт (а я не работал ни с одним из разработчиков), довольно легко заметить разницу.


75
Ваши глаза могут обмануть вас, когда вы ожидаете увидеть "" вы можете легко принять "" за "". Вот почему легче редактировать то, что написал кто-то другой. У вашего мозга нет предвзятых представлений о тексте, поэтому легче выявлять аномалии.
tvanfosson

125
@tvanfosson: Так вас (или коллегу) действительно укусило это как ошибка? Я с подозрением отношусь к подобным претензиям, которые не вызвали проблем. Я использовал "" в течение многих лет, никогда не ошибаясь ...
Джон Скит

34
Лично я всегда использовал String.Empty, я использую заглавные буквы 'S' всякий раз, когда я хочу использовать статический метод для строки, это просто личное предпочтение, которое позволяет мне отличать тип от переменной. Но это всего лишь переход от использования StringUtils.EMPTY в commons.lang из Java. Один интересный момент - я почти слепой, и это определенно помогает читаемости.
Бретт Райан

79
Вы вдохновили меня начать разработку в Times New Roman.
Джастин Русбэтч

73
По какой-то непонятной причине string.Emptyне является константой . Это означает, что в ряде случаев, когда требуется постоянная времени компиляции, string.Emptyэто даже не допустимо. Это включает case ""в себя блоки в switchоператорах, значения по умолчанию необязательных параметров , параметры и свойства в применении атрибутов , а также множество других ситуаций (оставленных читателю). Поэтому, учитывая, что string.Emptyэто запрещено в некоторых общих ситуациях, лучше использовать ""соглашение везде.
Джеппе Стиг Нильсен

375

Там действительно нет никакой разницы с точки зрения производительности и кода. При тестировании производительности они переходили туда-сюда, между которыми один был быстрее другого, и только на миллисекунды.

Глядя на закулисный код, вы действительно не видите никакой разницы. Единственная разница в IL, который string.Emptyиспользует код операции ldsfld и ""использует код операции ldstr, но это только потому, чтоstring.Empty является статическим, и обе инструкции делают то же самое. Если вы посмотрите на сборку, которая производится, это точно так же.

Код C #

private void Test1()
{
    string test1 = string.Empty;    
    string test11 = test1;
}

private void Test2()
{
    string test2 = "";    
    string test22 = test2;
}

IL код

.method private hidebysig instance void 
          Test1() cil managed
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init ([0] string test1,
                [1] string test11)
  IL_0000:  nop
  IL_0001:  ldsfld     string [mscorlib]System.String::Empty
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.1
  IL_0009:  ret
} // end of method Form1::Test1
.method private hidebysig instance void 
        Test2() cil managed
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init ([0] string test2,
                [1] string test22)
  IL_0000:  nop
  IL_0001:  ldstr      ""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.1
  IL_0009:  ret
} // end of method Form1::Test2

Код сборки

        string test1 = string.Empty;
0000003a  mov         eax,dword ptr ds:[022A102Ch] 
0000003f  mov         dword ptr [ebp-40h],eax 

        string test11 = test1;
00000042  mov         eax,dword ptr [ebp-40h] 
00000045  mov         dword ptr [ebp-44h],eax 
        string test2 = "";
0000003a  mov         eax,dword ptr ds:[022A202Ch] 
00000040  mov         dword ptr [ebp-40h],eax 

        string test22 = test2;
00000043  mov         eax,dword ptr [ebp-40h] 
00000046  mov         dword ptr [ebp-44h],eax 

13
@PrateekSaluja: Чтобы увидеть IL, вы можете использовать ildasm.exe, который поставляется вместе с Visual Studio. Чтобы увидеть дизассемблирование, используйте окно «Разборка» в меню отладки при достижении точки останова (работает и в коде выпуска).
Томас Братт

1
Ненавижу, что я собираюсь рекомендовать этот продукт .. НО ... отражатель позволяет вам выбирать ваш язык при разборке источника, и IL - вариант! ILDASM - это просто устаревшее чувство ... Команда MS tools, похоже, не полирует и не выпускает хорошие инструменты!
Felickz

80

Лучший код - это вообще не код :

Фундаментальный характер кодирования заключается в том, что наша задача как программистов состоит в том, чтобы признать, что каждое принятое нами решение является компромиссом. […] Начните с краткости. Увеличьте другие размеры в соответствии с требованиями тестирования.

Следовательно, меньше кода лучше код: Предпочитают ""в string.Emptyили String.Empty. Эти два в шесть раз больше без дополнительной выгоды - конечно, без дополнительной ясности, поскольку они выражают ту же самую информацию.


1
но в C # мы можем просто сказать string.IsNullOrWhitespace (s): p
felickz

31
Я согласен, что код должен быть как можно меньше, но, как правило, я не утверждаю, что меньшее количество символов всегда лучше кода. Например, когда дело доходит до именования переменных, разумное количество символов обычно приводит к лучшим именам, чем просто использование i и j.
Маркус Мейер

3
@Markus Это в значительной степени зависит: для переменного цикла , представляющих собой индекс, i это лучше , чем длинное имя переменного. Еще более общие, более короткие имена переменных, которые передают одну и ту же информацию с одинаковой ясностью, всегда предпочтительнее. Просто для того, чтобы выразить необходимую информацию, вам нужна определенная длина символа, и я не отрицаю этого (никто не является).
Конрад Рудольф

2
@Konrad: у меня хорошее имя переменной, только если цикл маленький и не содержит никаких других индексов. Но я согласен, что если что-н. можно сказать более кратко, передавая ту же информацию, которая была бы предпочтительнее, как в случае string.Empty / "". Строка. Пустая не добавляет ясности.
Маркус Мейер

Для меня: string.Empty говорит, что эта строка всегда и должна быть пустой, тогда как "" говорит, что во время написания эта строка может быть пустой, но вы можете изменить ее.
аэрозон

54

Единственное отличие состоит в том, что если вы используете switch-caseсинтаксис, вы не можете писать, case string.Empty:потому что это не константа. Вы получаетеCompilation error : A constant value is expected

Посмотрите на эту ссылку для получения дополнительной информации: строка-пусто-против-пусто-цитаты


22
switchУтверждение один очень хороший пример. Кроме того, если вы сделаете необязательный параметр, например void MyMethod(string optional = "") { ... }, это также невозможно использовать string.Empty. И затем, конечно, если вы хотите определить constполе или локальную переменную, const string myString = "";снова ""- единственный вариант. Если бы только string.Emptyбыло постоянное поле, не было бы разницы. Но это не так, поэтому в некоторых случаях вы должны использовать "". Так почему бы не использовать ""все время?
Джеппе Стиг Нильсен

5
Это действительно сильный аргумент, потому что использование string.Emptyпрепятствует достижению согласованности в вашей кодовой базе: вы должны использовать две разные сущности для выражения одной и той же вещи. И добавить в список вещей, которые вы не можете сделать: вы не можете использовать string.Emptyс атрибутами .
Прагматик

2
Очень хорошие очки! Ссылка не работает. Вот копия содержимого: web.archive.org/web/20131230161806/http://kossovsky.net/…
ygoe

42

Я предпочел бы , stringчтобыString . выбирая string.Emptyболее ""является вопросом выбора одного и приклеить с ним. Преимущество использования в string.Emptyтом, что оно совершенно очевидно, что вы имеете в виду, и вы случайно не копируете непечатные символы, как "\x003"у вас "".


101
Я бы сказал, что если вы случайно копируете непечатаемые символы в свой код, у вас есть более серьезные проблемы, чем этот вопрос;)
Джон Скит

9
ASCII \ 003 является разделителем полей для сообщений B2B, с которыми я работал :)
Джимми

7
(Я бы также предложил избегать побега \ x, кстати - слишком трудно определить разницу между "\ x9Bad Compiler" и "\ x9Good Compiler", которые имеют радикально разные результаты!)
Джон Скит

Лично я предпочитаю String, а не строку при вызове статического метода для String. Я почти слеп, однако, и это личное предпочтение, которое я никому не навязываю.
Бретт Райан

2
@ Джимми Конечно, но мы говорили о пустой строке. ""Я утверждаю, что аргумент, который опасен, когда копирование / вставка является недействительным, потому что вы никогда не копируете / вставляете пустую строку. Что касается других строк, это, конечно, всегда нужно помнить.
Тимо

22

Я не собирался вмешиваться, но я вижу, что здесь выкидывают какую-то неправильную информацию.

Я лично предпочитаю string.Empty. Это личное предпочтение, и я подчиняюсь воле любой команды, с которой работаю, в каждом конкретном случае.

Как уже упоминали некоторые другие, между string.Emptyи String.Empty.

Кроме того, и это малоизвестный факт, использование «» вполне приемлемо. Каждый экземпляр «» в других средах создает объект. Однако .NET интернирует свои строки, поэтому будущие экземпляры будут извлекать ту же неизменяемую строку из внутреннего пула, и любое снижение производительности будет незначительным. Источник: Брэд Абрамс .


20
Я не понимаю, почему «технически» каждый экземпляр «» создает объект. Это не просто шанс, что строки интернированы - это в спецификации C #.
Джон Скит

15

Я лично предпочитаю "", если нет веских причин для чего-то более сложного.


13

String.Emptyи string.Emptyэквивалентны. Stringимя класса BCL; stringэто его псевдоним C # (или ярлык, если хотите). То же, что Int32и с int. Посмотреть документы для большего количества примеров.

Так далеко как "" касается этого, я не совсем уверен.

Лично я всегда пользуюсь string.Empty.


10

Почти каждый разработчик знает, что означает "". Я лично столкнулся со String.Empty в первый раз, и мне пришлось потратить некоторое время на поиск в Google, чтобы выяснить, действительно ли это одно и то же.


3
Это общедоступное строковое поле, доступное только для чтения, и его значения "" ... почему это изменится?
Мэтью Уайтед

5
Вы упускаете из виду то, что @Jason делает. Откуда ты знаешь, что ты видишь впервые string.Empty? Знаете ли вы, что ""вы впервые увидели?
Дэвид Р. Триббл

10

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

Я нашел разницу в поведении компилятора, если вы используете string.Emptyили двойные кавычки. Разница проявляется, если вы не используете строковую переменную, инициализированную string.Empty или двойными кавычками.

В случае инициализации с string.Emptyпоследующим предупреждением компилятора

CS0219 - The variable 'x' is assigned but its value is never used

никогда не генерируется, в то время как в случае инициализации двойными кавычками вы получаете ожидаемое сообщение.

Это поведение объясняется в статье Connect по этой ссылке: https://connect.microsoft.com/VisualStudio/feedback/details/799810/c-warning-cs0219-not-reported-when-assign-non-constant-value

По сути, если я правильно понял, они хотят позволить программисту установить переменную с возвращаемым значением функции для целей отладки, не отвлекая его предупреждающим сообщением, и, таким образом, они ограничивают предупреждение только в случае присваиваний и строк. Пусто не константа, а поле.


1
Я верю, что ты первый, кто упомянул. Я прочитал этот вопрос и ответы несколько месяцев назад и не помню этой разницы, которая была бы, если бы она была упомянута.
Палек

2
Интересно. Обратите внимание, что объявление var unused = "literal";может быть полностью оптимизировано (удалено) компилятором. У него не может быть побочных эффектов. С другой стороны, var unused = MyClass.Member;не может быть удален полностью. Это потому, что чтение Memberможет иметь побочные эффекты. Если Memberстатическое свойство getимеет метод доступа, то ясно, что вызов метода получения должен быть сохранен. Но даже если Memberэто статическое поле, может возникнуть побочный эффект от запуска статического конструктора. Конечно, это будет плохой стиль кодирования . Но тебе нужен манекен, чтобы читать Member.
Джеппе Стиг Нильсен

9

Я выполнил этот очень простой тест, используя следующий метод в консольном приложении:

private static void CompareStringConstants()
{
    string str1 = "";
    string str2 = string.Empty;
    string str3 = String.Empty;
    Console.WriteLine(object.ReferenceEquals(str1, str2)); //prints True
    Console.WriteLine(object.ReferenceEquals(str2, str3)); //prints True
}

Это ясно говорит о том, что все три переменные, а именно str1, str2и str3хотя они инициализируются с использованием другого синтаксиса, указывают на один и тот же строковый (нулевой длины) объект в памяти. Я выполнил этот тест в консольном приложении .NET 4.5. Внутренне они не имеют никакой разницы, и все сводится к удобству того, которое вы хотите использовать в качестве программиста. Такое поведение строкового класса известно как интернирование строк в .NET. Эрик Липперто имеет очень хороший блог здесь , описывающий эту концепцию.


8

Любой из вышеперечисленных.

Есть много, много лучших вещей для изучения. Например, какой цвет коры подходит к дереву лучше всего, я думаю, что смутно-коричневый с оттенками мха Дульсет.


7

Я настоятельно предпочитаю String.Empty, помимо других причин, чтобы вы знали, что это такое, и что вы не случайно удалили содержимое, но в первую очередь для интернационализации. Если я вижу строку в кавычках, я всегда задаюсь вопросом, является ли это новым кодом, и его следует поместить в таблицу строк. Поэтому каждый раз, когда код изменяется / пересматривается, вам нужно искать «что-то в кавычках», и да, вы можете отфильтровывать пустые строки, но я говорю людям, что это хорошая практика - никогда не помещать строки в кавычки, если вы не знаете, что они не будут локализованы. ,


7

Никто не упомянул, что в VisualStudio String кодируется цветом иначе, чем строка. Что важно для читабельности. Кроме того, строчные буквы обычно используются для переменных и типов, что не имеет большого значения, но String.Empty - это константа, а не переменная или тип.


String.Empty не является константой: см. Stackoverflow.com/questions/507923/… По сути, это экземпляр класса String. А цвет уже упоминался, хотя и немного скрытый: stackoverflow.com/questions/263191/…
Майкл

6

stringэто синоним для System.Stringтипа, они идентичны.

Значения также идентичны: string.Empty == String.Empty == ""

Я бы не использовал символьную константу "" в коде, точнее string.Emptyили String.Empty- проще понять, что имел в виду программист.

Между stringи Stringмне больше нравятся строчные буквы stringтолько потому, что я работал с Delphi много лет, а стиль Delphi - строчныеstring .

Итак, если бы я был вашим начальником, вы бы написали string.Empty


6

Я предпочла бы string.Emptyболее String.Emptyпотому , что вы можете использовать его без необходимости включать в себяusing System; в файл.

Что касается выбора ""более string.Empty, это личные предпочтения и должно быть принято вашей командой.


2
Я единственный член команды, как мне решить? бросить кости?
Gqqnbig

1
Для тех, кому может быть интересно узнать, как можно использовать string.Emptyконстанту без импорта using Systemпространства имен - ключевые слова в C # просто преобразуются в их полностью квалифицированное имя, которое также включает пространство имен, прежде чем записываться в виде MSIL в выходных данных * .dll или *. EXE-файл. Так эффективно string.Emptyзаписывается как System.String.Emptyв MSIL компилятором. И, как вы уже знаете, если вы упомянули полное имя типа, вы можете пропустить импорт пространств имен в верхней части вашего файла кода.
RBT

5

Я не имею никакого значения. Последний самый быстрый, чтобы напечатать хотя :)


4

Это не имеет значения - это одно и то же. Тем не менее, главное, что вы должны быть последовательными

PS Я все время борюсь с этим "что правильно".


1
В современном мире «согласованность» означает согласованность во всех командах по всему миру, что является одной из целей StackOverflow. Если я могу предложить, давайте использовать String.Empty.
Павел Радзивиловский

1
В некоторых языках нет константы Empty, и все языки, о которых я могу подумать, допускают "" строку нулевой длины. Поэтому я голосую за "" за согласованность с другими языками. :)
TomXP411

4

Это полностью предпочтение в стиле кода, подход к тому, как .NET обрабатывает строки. Впрочем, вот мои мнения :)

Я всегда использую имена BCL Type при доступе статические методы, свойства и поля: String.Emptyили Int32.TryParse(...)илиDouble.Epsilon

Я всегда использую ключевые слова C # при объявлении новых экземпляров: int i = 0;илиstring foo = "bar";

Я редко использую необъявленные строковые литералы, так как мне нравится иметь возможность сканировать код, чтобы объединить их в повторно используемые именованные константы. В любом случае компилятор заменяет константы на литералы, так что это скорее способ избежать магических строк / чисел и придать им немного больше значения с помощью имени. Плюс изменить значения проще.


3

Я использую третий, но из двух других первый кажется менее странным. Строка является псевдонимом для String, но, видя их в задании, не имеет смысла.


3

Любой из первых двух будет приемлем для меня. Я бы избежал последнего, потому что относительно легко ввести ошибку, поместив пробел между кавычками. Эту конкретную ошибку было бы трудно обнаружить наблюдением. При условии отсутствия опечаток, все семантически эквивалентны.

[РЕДАКТИРОВАТЬ]

Кроме того , вы можете всегда использовать либо stringили Stringдля последовательности, но это только мне.


Я согласен с этим замечанием, но я все еще живу опасно, когда мне лень. В любом случае, я не думаю, что у меня есть повод написать код, который использует строку, прежде чем присваивать ей вне объявления переменной. На самом деле, меня раздражает, что я должен инициализировать свои строки вообще, несмотря на риски.
EnocNRoll - AnandaGopal Pardue

3

Я лично был свидетелем "", приводящего к (незначительным) проблемам дважды. Однажды это произошло из-за ошибки начинающего разработчика, плохо знакомого с командным программированием, а другая была простой опечаткой, но факт использовал string.Empty избежал бы обеих проблем.

Да, это в значительной степени суждение, но когда язык дает вам несколько способов сделать что-то, я склоняюсь к тому, который обладает наибольшим контролем над компилятором и самым сильным соблюдением времени компиляции. Это не "". Это все о выражении конкретных намерений.

Если вы введете string.EMpty или Strng.Empty, компилятор сообщит вам, что вы ошиблись. Немедленно. Он просто не скомпилируется. Как разработчик, вы ссылаетесь на конкретное намерение, которое компилятор (или другой разработчик) не может никоим образом неверно истолковать, а если вы сделаете это неправильно, вы не сможете создать ошибку.

Если вы наберете «», когда имеете в виду «» или наоборот, компилятор с радостью сделает то, что вы сказали. Другой разработчик может или не сможет найти ваши конкретные намерения. Ошибка создана.

Задолго до string.Empty я использовал стандартную библиотеку, которая определяла константу EMPTY_STRING. Мы по-прежнему используем эту константу в операторах case, где string.Empty не допускается.

Когда бы ни было возможно, заставьте компилятор работать на вас, и исключите возможность человеческой ошибки, независимо от того, насколько она мала. ИМО, это козыри "читабельности", как цитировали другие.

Специфика и время компиляции. Это то, что на ужин.


3

Я использую "", потому что в моем коде он будет ярко окрашен в желтый цвет ... по какой-то причине String.Empty полностью белый в моей теме кода Visual Studio. И я считаю, что это имеет для меня самое большое значение.


2

Компилятор должен сделать их все равно в долгосрочной перспективе. Выберите стандарт, чтобы ваш код было легко читать, и придерживайтесь его.


2

Я просто смотрел какой-то код, и этот вопрос всплыл у меня в голове, который я прочитал некоторое время назад. Это, безусловно, вопрос читабельности.

Рассмотрим следующий код C # ...

(customer == null) ? "" : customer.Name

против

(customer == null) ? string.empty : customer.Name

Лично я нахожу последние менее двусмысленными и более легкими для чтения.

Как отмечают другие, фактические различия незначительны.


1

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


1

Хотя разница очень, ОЧЕНЬ мала, разница все же существует.

1) "" создает объект, а String.Empty - нет. Но этот объект будет создан один раз и на него будут ссылаться из пула строк позже, если у вас есть еще один символ "" в коде.

2) Строка и строка одинаковы, но я бы порекомендовал использовать String.Empty (а также String.Format, String.Copy и т. Д.), Поскольку точечная нотация указывает на класс, а не на оператора, а класс, начинающийся с заглавной буквы, соответствует C # стандарты кодирования.


1
string.Empty is "", проверьте источник
dss539

1

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

Как видно Дэвид, там разница между String.Emptyи ""довольно мала, но есть разница. ""на самом деле создает объект, он, скорее всего, будет извлечен из внутреннего пула строк, но все же ... пока не String.Emptyсоздает объект ... поэтому, если вы действительно ищете в конечном итоге в эффективности памяти, я предлагаю String.Empty. Тем не менее, вы должны иметь в виду, что разница настолько незначительна, что вы никогда не захотите видеть ее в своем коде ...
Что касается System.String.Emptyили string.Emptyили String.Empty... мой уровень обслуживания низкий ;-)


1
Это сообщение в блоге MSDN было в 2003 году ... Вы уверены, что это все еще верно для последних версий .NET ?!
Карстен Шютте

@ CarstenSchütte: мне кажется, что такая функция не должна сильно меняться ... и если бы это было так, в интернете был какой-то шум по этому поводу.
sergiol

3
@sergiol Если поле более эффективно, чем литерал, это однозначно ошибка производительности. Так что есть надежда, что это будет исправлено к настоящему времени.
Конрад Рудольф

1

Пустая строка похожа на пустой набор, просто имя, которое все используют для вызова "". Также в формальных языках строки, созданные из алфавита с нулевой длиной, называются пустой строкой. И set, и string имеют специальный символ для этого. Пустая строка: ε и пустое множество: ∅. Если вы хотите поговорить об этой строке нулевой длины, вы назовете ее пустой строкой, чтобы все точно знали, на что вы ссылаетесь. Теперь, если вы называете ее пустой строкой, почему бы не использовать ее string.Emptyв коде, она показывает, что намерение является явным. Недостатком является то, что он не является константой и поэтому не доступен везде, как в атрибутах. (Это не константа по некоторым техническим причинам, см. Справочный источник.)


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.