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

643

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

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

string willi = string.Empty;

или

string willi = string.Empty;

или

string willi = "";

или что?

  • 5
    Смотрите также это аналогичное обсуждение для Java: stackoverflow.com/questions/213985/…
  • 0
    Что еще важнее, никогда не сравнивать строку с Sting.Empty. <br> Плохо: if (s == "") <br> Хорошо: if (s.Length == 0)
Показать ещё 8 комментариев
Теги:
string
initialization

29 ответов

702
Лучший ответ

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

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

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

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

  • 73
    Ваши глаза могут обмануть вас, когда вы ожидаете увидеть "" вы можете легко принять "" за "". Вот почему легче редактировать то, что написал кто-то другой. У вашего мозга нет предвзятых представлений о тексте, поэтому легче выявлять аномалии.
  • 111
    @tvanfosson: Так вас (или коллегу) действительно укусило это как ошибка? Я с подозрением отношусь к подобным претензиям, которые не вызвали проблем. Я использовал "" в течение многих лет, никогда не ошибаясь ...
Показать ещё 31 комментарий
379

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

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

Код С#

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 
  • 12
    @PrateekSaluja: Чтобы увидеть IL, вы можете использовать ildasm.exe, который поставляется вместе с Visual Studio. Чтобы увидеть дизассемблирование, используйте окно «Разборка» в меню отладки при достижении точки останова (работает и в коде релиза).
  • 1
    Ненавижу, что я собираюсь рекомендовать этот продукт .. НО ... отражатель позволяет вам выбирать ваш язык при разборке источника, и IL - вариант! ILDASM - это просто устаревшее чувство ... Команда MS tools, похоже, не полирует и не выпускает хорошие инструменты!
71

Лучший код не является кодом вообще:

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

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

  • 1
    но в C # мы можем просто сказать string.IsNullOrWhitespace (s): p
  • 25
    Я согласен, что код должен быть как можно меньше, но, как правило, я не утверждаю, что меньшее количество символов всегда лучше кода. Например, когда дело доходит до именования переменных, разумное количество символов обычно приводит к лучшим именам, чем просто использование i и j.
Показать ещё 8 комментариев
47

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

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

  • 20
    Оператор switch - один из очень хороших примеров. Кроме того, если вы сделаете необязательный параметр, такой как void MyMethod(string optional = "") { ... } , также невозможно использовать string.Empty . И, конечно же, если вы хотите определить поле const или локальную переменную, const string myString = ""; снова "" - единственный вариант. Если бы только string.Empty было постоянным полем, не было бы разницы. Но это не так, поэтому в некоторых случаях вы должны использовать "" . Так почему бы не использовать "" все время?
  • 4
    Это действительно сильный аргумент, потому что использование string.Empty позволяет вам достичь согласованности в вашей кодовой базе: вы должны использовать две разные сущности для выражения одной и той же вещи. И чтобы добавить в список вещей, которые вы не можете сделать: вы не можете использовать string.Empty с атрибутами .
Показать ещё 1 комментарий
41

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

  • 95
    Я бы сказал, что если вы случайно копируете непечатаемые символы в свой код, у вас больше проблем, чем в этом вопросе;)
  • 9
    ASCII \ 003 является разделителем полей для сообщений B2B, с которыми я работал :)
Показать ещё 7 комментариев
19

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

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

Как уже отмечали некоторые другие, между string.Empty и string.Empty нет никакой разницы.

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

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

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

12

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

Что касается "", я не уверен.

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

10

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

  • 3
    Это общедоступное строковое поле, доступное только для чтения, и его значения "" ... почему это изменится?
  • 5
    Вы упускаете из виду то, что @Jason делает. Откуда вы знаете, что это первый раз, когда вы видите string.Empty ? Знаете ли вы, что "" впервые увидел это?
8

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

Я нашел разницу в поведении компилятора, если вы используете 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

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

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

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

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. Эрик Липперт имеет очень хороший блог здесь, описывающий эту концепцию.

6

Любое из приведенных выше.

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

5

Никто не упоминал, что в VisualStudio String по-разному кодируется цвет, а затем строка. Это важно для читаемости. Кроме того, нижний регистр обычно используется для vars и типа, но не большой, но String.Empty является константой, а не var или type.

5

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

4

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

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

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

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

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

4

Я не понимаю. Последнее самое быстрое: #

3

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

p.s. Я все время борюсь с такими "правильными".

  • 1
    В современном мире «согласованность» означает согласованность во всех командах по всему миру, что является одной из целей StackOverflow. Если я могу предложить, давайте использовать String.Empty.
  • 1
    В некоторых языках нет константы Empty, и все языки, о которых я могу подумать, допускают "" строку нулевой длины. Поэтому я голосую за "" за согласованность с другими языками. :)
2

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

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

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

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

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

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

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

2

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

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

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

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

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

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

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

2

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

[EDIT]

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

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

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

1

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

1

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

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

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

против

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

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

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

1

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

0

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

0

Вкл 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 ?!
  • 0
    @ CarstenSchütte: мне кажется, что такая функция не должна сильно меняться ... и если бы это было так, в интернете был какой-то шум по этому поводу.
Показать ещё 1 комментарий
0

В то время как разница очень, очень немного, разница все еще существует.

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню