Невозможно использовать String.Empty в качестве значения по умолчанию для необязательного параметра

89

Я читаю « Эффективный C # » Билла Вагнера. В элементе 14 - Минимизация логики повторяющейся инициализации он показывает следующий пример использования новых дополнительных параметров в конструкторе:

public MyClass(int initialCount = 0, string name = "")

Обратите внимание, что он использовал ""вместо string.Empty.
Он комментирует:

Вы заметите [в примере выше], что второй конструктор указал "" для значения по умолчанию в параметре name , а не более привычного string.Empty. Это потому, что string.Emptyэто не константа времени компиляции. Это статическое свойство, определенное в строковом классе. Поскольку это не константа компиляции, вы не можете использовать ее в качестве значения по умолчанию для параметра.

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

ОБНОВЛЕНИЕ
Просто следующий комментарий. Согласно MSDN:

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

Тогда мы не сможем System.Environment.NewLineни использовать , ни использовать вновь созданные объекты в качестве значений по умолчанию. Я еще не использовал VS2010, и это разочаровывает!

Mikeyg36
источник
2
Мне не известно о каких-либо различиях между тем, как пустые строки представлены на разных платформах. Это не похоже на новую строку.
Том Кабански,
Правильно, я подумал об этом, значит, это просто выглядит лучше в коде?
Mikeyg36,
1
CLR, а не «Система», является определяющим фактором относительно того, является ли "" пустой строкой или нет. Поэтому я думаю, вы можете смело предположить, что "" - это системно-независимый способ ссылки на строку в совместимой реализации CLR.
Крис Тейлор,
«системно-независимый»? э-э, в отличие от системного ""? (???)
Qwertie
Согласно MSDN: значение этого поля - строка нулевой длины "". так что, очевидно, это не имеет ничего общего с независимостью от платформы, как указывают многие люди. И все же кажется, что люди действительно не знают, зачем его использовать!
Mikeyg36

Ответы:

66

Что касается компилятора C # 2.0, в String.Emptyлюбом случае здесь очень мало смысла , и на самом деле во многих случаях это пессимизация, поскольку компилятор может встроить некоторые ссылки, ""но не может сделать то же самое с String.Empty.

В C # 1.1 было полезно избегать создания множества независимых объектов, содержащих пустую строку, но те времена прошли. ""работает нормально.

Энди Мортимер
источник
7
Даже в .NET 1.1 он не создавал бы «много» независимых объектов. Я не могу вспомнить подробности различий между 1.1 и 2.0 в этом отношении, но это не похоже на то, что интернирование строковых литералов было введено только в 2.0.
Джон Скит,
Благодарю за разъяснение. Я осмотрелся и не нашел подробного описания изменений в C # 2.0, хотя уверен, что уже читал одно раньше. Я нашел ответ StackOverflow от 2008 года с некоторыми ссылками на дополнительную техническую информацию. stackoverflow.com/questions/151472/…
Энди Мортимер
1
Я дам ему кивок, хотя мне не нравится говорить, что в нити нет смысла. Пусто, поскольку я использую его довольно часто. Я считаю, что он просто выглядит чище, хотя это мое личное мнение. Есть много мест, где string.Empty использовать нельзя, и у меня нет проблем с использованием "" в этих случаях
xximjasonxx
15
Я обнаружил, что гораздо проще быстро идентифицировать пустую строку с помощью String.Empty, чем дважды смотреть на "", чтобы убедиться, что в ней нет апострофа или чего-то подобного, спрятанного в ней. +1 за объяснение.
NotMe
11
+1 Крис. Также в VS вы действительно не можете выполнять поиск по использованию "" (кроме выполнения стандартного поиска, который также возвращает каждое совпадение текста, включая комментарии и разметку). Вы можете выполнить поиск по конкретному использованию кода с помощью string.Empty.
MutantNinjaCodeMonkey
53

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

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[Как в сторону, одна из причин предпочитать String.Emptyболее чем ""в целом, что не было упомянуто в других ответов, является то , что существуют различные символы Unicode (нулевой ширины столяры, и т.д.), которые эффективно невидимые невооруженным глазом. То есть то, что выглядит как ""пустая строка, не обязательно является пустой строкой, тогда как String.Emptyвы точно знаете, что используете. Я понимаю, что это не общий источник ошибок, но это возможно.]

Мэтью Стробридж
источник
2
Есть также невидимые символы-идентификаторы, поэтому что-то похожее на String_Empty не обязательно. В стандарте Unicode есть глава о соображениях безопасности, на которую в основном не обращают внимания.
Джим Балтер,
25

Из исходного вопроса:

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

Каким образом пустая строка может отличаться от системы к системе? Это всегда строка без символов! Мне было бы очень страшно, если бы я когда-нибудь нашел реализацию, в которой string.Empty == ""возвращается false :) Это не то же самое, что что-то вроде Environment.NewLine.

Из сообщения о награде Counter Terrorist:

Я хочу, чтобы String.Empty можно было использовать в качестве параметра по умолчанию в следующем выпуске C #. : D

Что ж, этого точно не произойдет.

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

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

Вот что меня удивляет в этом вопросе - жалоба вращается вокруг чего-то, что на самом деле не вызывает реальной проблемы. Это более важно в тех случаях, когда вы хотите, чтобы значение по умолчанию вычислялось во время выполнения, потому что оно может действительно отличаться. Например, я мог бы представить себе случаи, когда вы хотите иметь возможность вызывать метод с DateTimeпараметром и по умолчанию использовать «текущее время». На данный момент я знаю только один нечетко элегантный обходной путь:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

... но это не всегда уместно.

В заключении:

  • Я очень сомневаюсь, что это когда-нибудь станет частью C #
  • В string.Emptyлюбом случае это бессмысленно
  • Для других значений, которые на самом деле не всегда одинаковы, это действительно может быть болью
Джон Скит
источник
На самом деле это хороший способ решить проблему. То же самое можно использовать для переноса / установки других переменных, зависящих от устройства, например Environment.Newline.. Единственное, чего не хватает в вашем примере, - это проверка переменной на значение NULL и возврат исключения разработчику, сообщающий ему, что, хотя оно допускает значение NULL, оно не принял. if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}или что-то типа того. Но мне это очень нравится! Есть ли другие предостережения, чтобы делать это по-своему?
MaxOvrdrv
@MaxOvrdrv: вы не хотите, чтобы значение null было ошибкой - все дело в том, что когда оно равно null, вы вычисляете значение по умолчанию. Предостережение заключается в том, что он не позволяет передавать null как допустимое значение само по себе.
Джон Скит
Вы совершенно правы. Виноват. - И да, это была бы единственная настоящая оговорка, не так ли ... это не так уж и плохо. Еще раз: мне очень нравится это решение! :) Спасибо, что разместили! :)
MaxOvrdrv
7

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

Ханс Ольссон
источник
2
Может быть, это предотвращает путаницу ""и " ", но я не могу сказать, что " "это все, что обычно.
Грег
8
Я бы посоветовал любому, кто не видит разницы между ними, нужны либо лучшие очки, либо меньшее разрешение экрана. У меня плохое зрение, и я не могу припомнить, чтобы когда-либо совершал эту ошибку (и мне действительно приходится работать с большим количеством кода, который содержит и то, и другое).
Ханс Олссон,
2
string.Empty полезна, чтобы узнать точное намерение программиста. "" ничего не говорит о намерении, что, если намерение программиста состояло в том, чтобы инициализировать переменную, как это "lol", но забыл ... в этом случае есть бесконечные возможности и строка, Empty пригодится и работает лучше
полезныйBee
4

Я думаю, что идея string.Empty в том, что она улучшает читаемость. Это не похоже на новую строку, где есть разница между тем, как она представлена ​​на разных платформах. Жаль, что это нельзя использовать в параметре по умолчанию. Однако при переносе между Windows и чем-то вроде Mono в Linux это не вызовет никаких проблем.

Том Кабански
источник
5
Думаю, вы, наверное, правы, дело в том, что некоторые люди считают его String.Emptyболее читабельным. . . Хотя лично я считаю это немного сумасшедшим. ""вероятно, самая распространенная строка из существующих, и все видели ее миллиард раз, так почему же она нечитаема? String.Emptyпримерно так же полезен, как если бы существовал Int32.Zero.
Тим Гудман,
3

К вашему сведению, похоже, что такое же ограничение накладывается на значения, передаваемые конструкторам атрибутов - они должны быть постоянными. Поскольку string.empty определяется как:

public static readonly string Empty

вместо фактической константы его нельзя использовать.

Шон Ивис
источник
2

Использую string.Emptyчисто для читабельности.

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

Например:

if(someString == string.Empty)
{

}

против

if(someString == "")
{

}

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

Lukejkw
источник
-2

Возможно, лучшим решением этой проблемы является перегрузка этого метода следующим образом:

public static void PrintString() 
{ 
    PrintString(string.Empty);
}
lokum09
источник
3
Как это ответить на поставленный выше вопрос?
Пранав Сингх
1
Как это помогает со значениями по умолчанию для дополнительных параметров?
локаль по умолчанию