В чем смысл свойства string.Empty


35

Почему собственность была string foo = string.Emptyвключена в BCL? Это кажется более многословным и не более понятным, чем просто использование пустой строки ( string foo = "")


6
Nitpick: Это не часть языка. Это часть BCL. VB.NET и F # могут использовать его, как и любой другой язык .NET.
Одед

19
Потому что иначе нельзя было бы совершать такие злые поступки, как typeof(string).GetField("Empty").SetValue(null, " ");;)
Мейсон Уилер

1
@MasonWheeler - радости размышления. Для настоящего зла тебе нужен самоанализ, а?
Одед

1
@MasonWheeler, +1. О боже, очки, они ничего не делают!]
Мачадо

1
@MasonWheeler Это чистое, дистиллированное зло. Мне это нравится. Вопрос, если вам интересно: не было бы безопаснее (и приличнее) написать это как public static string Empty { get { return string.Intern(""); } }?
Джесси С. Slicer

Ответы:


55

Я могу только предположить здесь:

string.Emptyбыл определен для явности - при инициализации строки это может быть непонятно из контекста, который ""действительно явно подразумевался как инициализатор (вместо nullили, скажем, " "или просто как заполнитель во время тестирования). Использование string.Empty- это определенный ответ на такую ​​головоломку.

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

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


5
+1 за то, что пока единственный правильный ответ.
PSR

Некоторые языки могут даже не иметь пустой строковый литерал. Видимо, стандартный Паскаль не сделал.
Ден04

2
«пустая строка в C не является пустой строкой» - но, тем не менее, если вы напишите "", вы получите {'\0'}, так что не будет никакой разницы между литералом пустой строки и каким-либо другим окольным способом ее определения.
детально

14

Я не уверен на 100% в источниках, где я их узнал, но некоторые из пунктов его использования включают:

  • Каждая строка в сборке .NET уникальна, поэтому

    string foo = "";
    string bar = "";

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

  • Ясность. Когда вы сталкиваетесь string.Emptyс намерением, становится ясно, что это должна быть пустая строка. Но если вы столкнулись с foo = ""тем, что программист удалил содержимое строки во время тестирования и забыл добавить ее обратно, или это должно быть так?

1
Казалось бы, странным было бы хранить в памяти две одинаковые строки. Это на самом деле то, что сделано?
Буровая установка

36
На самом деле все наоборот - это интернирование строк (точнее интернирование литералов). Я точно знаю, что это сделано в Java и Python, и я почти уверен, что это так и в языках .NET. Конечно, это может происходить только в пределах одной единицы перевода, поэтому, если динамический загрузчик не объединит такие данные, вы можете получить одну пустую строку на программный файл. Все еще не очень много.

9
@delnan абсолютно прав. ""/ string.Emptyинтернированы, и будет создан только один объект.
Одд

11
@Andy - все строковые литералы интернированы в .NET. Не все строки. Программно созданные строки по умолчанию не интернированы. Смотрите String.Intern на MSDN.
Одд

3
@Oded et alia: На самом деле никто из вас не прав. Во-первых, литералы интернированы внутри сборки, но не обязательно между сборками . Во-вторых, детально ли реализована пустая строка между сборками? некоторые версии CLR делают, а некоторые нет. Там есть ссылка на мою статью об этом факте в одном из других ответов; смотрите это для деталей.
Эрик Липперт

2

Объект не будет создан для string.Empty. Использование ""создаст объект, который, скорее всего, будет исходить из пула интернированных строк.

В прошлом люди запускали тесты и String.Emptyвыходили чуть быстрее, но это микрооптимизация.

String.Empty это:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 

2
Итак, ваша точка зрения ...?

1
Дело в том, что String.Empty в основном является константой для "". Найдите автора String.cs для более глубокого смысла. :)
Джон Рейнор

0

Это вопрос оптимизации использования памяти и оптимизации сравнения строк. Каждый раз, когда вы используете пустую строку в вашем приложении, вы выделяете строковый объект, содержащий 0 символов. Что касается сравнения строк, это можно сделать, сравнивая ссылки (указатели) вместо символьных, что быстрее даже для пустых строк.

Если вы много раз используете одну и ту же строку в своем приложении, вы можете использовать один и тот же тип механизма, вызывая String.Intern () со своей строкой. Но если вы используете каждую строку только один раз, тогда вы будете использовать только больше памяти.

Так что String.Empty - это только особый вариант оптимизации, который стоит делать для большинства приложений .Net, поэтому он был интегрирован в BCL.

Для более подробной информации по этому вопросу я настоятельно рекомендую прочитать сообщение в блоге Эрика Липперта .

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


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

7
@ChrisF: я не могу реорганизовать блог. Это было бы серьезным изменением, и вы знаете, как я к ним отношусь.
Эрик Липперт

1
@EricLippert - я понимаю, что вы никогда этого не сделаете, однако ответы только по ссылкам не являются хорошими ответами, и мы должны поощрять людей осознавать это.
ChrisF

3
@EricLippert Это не просто эфемерные ссылки. Здесь также говорится о вежливости по отношению к читателям: в ответе должно быть как минимум достаточно контента, чтобы читатели могли составить мнение о том, следует ли переходить по ссылке. И ответ должен иметь смысл даже в автономной копии SE.
Жиль "ТАК ... перестать быть злым"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.