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

Я читаю Эффективный С# Билл Вагнер. В пункте 14 "Сведение к минимуму дублирующей логики инициализации" он показывает следующий пример использования функции дополнительных необязательных параметров в конструкторе:

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

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

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

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

UPDATE
Просто комментарий. Согласно MSDN:

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

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

Ответ 1

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

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

Ответ 2

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

const string String_Empty = "";

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

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

Ответ 3

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

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

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

От Counter Terrorist bounty post:

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

Хорошо, что, конечно, этого не произойдет.

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

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

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

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

... но это не всегда подходит.

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

public static readonly string Empty

а не фактическую константу, ее нельзя использовать.

Ответ 7

Если вам действительно не нравятся строковые литералы, вы можете использовать:

public static string MyFunction(string myParam= default(string))

Ответ 8

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

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

Например:

if(someString == string.Empty)
{

}

против

if(someString == "")
{

}

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

Ответ 9

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

public static void PrintString() 
{ 
    PrintString(string.Empty);
}