Почему собственность была string foo = string.Emptyвключена в BCL? Это кажется более многословным и не более понятным, чем просто использование пустой строки ( string foo = "")
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- "". Каждый раз, когда любое из них повторяется в коде, объект будет извлечен из внутреннего пула. Это верно для домена приложения .
Некоторые языки могут даже не иметь пустой строковый литерал. Видимо, стандартный Паскаль не сделал.
Ден04
2
«пустая строка в C не является пустой строкой» - но, тем не менее, если вы напишите "", вы получите {'\0'}, так что не будет никакой разницы между литералом пустой строки и каким-либо другим окольным способом ее определения.
детально
14
Я не уверен на 100% в источниках, где я их узнал, но некоторые из пунктов его использования включают:
Каждая строка в сборке .NET уникальна, поэтому
string foo ="";string bar ="";
приводит к 2 строкам в выходной сборке, так как строки являются неизменяемыми. Наличие обеих ссылок string.Emptyуменьшает размер сборки.
Ясность. Когда вы сталкиваетесь string.Emptyс намерением, становится ясно, что это должна быть пустая строка. Но если вы столкнулись с foo = ""тем, что программист удалил содержимое строки во время тестирования и забыл добавить ее обратно, или это должно быть так?
Казалось бы, странным было бы хранить в памяти две одинаковые строки. Это на самом деле то, что сделано?
Буровая установка
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. publicstaticreadonlyStringEmpty="";
Дело в том, что String.Empty в основном является константой для "". Найдите автора String.cs для более глубокого смысла. :)
Джон Рейнор
0
Это вопрос оптимизации использования памяти и оптимизации сравнения строк. Каждый раз, когда вы используете пустую строку в вашем приложении, вы выделяете строковый объект, содержащий 0 символов. Что касается сравнения строк, это можно сделать, сравнивая ссылки (указатели) вместо символьных, что быстрее даже для пустых строк.
Если вы много раз используете одну и ту же строку в своем приложении, вы можете использовать один и тот же тип механизма, вызывая String.Intern () со своей строкой. Но если вы используете каждую строку только один раз, тогда вы будете использовать только больше памяти.
Так что String.Empty - это только особый вариант оптимизации, который стоит делать для большинства приложений .Net, поэтому он был интегрирован в BCL.
Ответы только на ссылки не дают хороших ответов. Если Эрик когда-нибудь реорганизует свой блог, этот ответ станет бесполезным. Пожалуйста, кратко изложите этот пост здесь, чтобы у нас была вся информация.
ChrisF
7
@ChrisF: я не могу реорганизовать блог. Это было бы серьезным изменением, и вы знаете, как я к ним отношусь.
Эрик Липперт
1
@EricLippert - я понимаю, что вы никогда этого не сделаете, однако ответы только по ссылкам не являются хорошими ответами, и мы должны поощрять людей осознавать это.
ChrisF
3
@EricLippert Это не просто эфемерные ссылки. Здесь также говорится о вежливости по отношению к читателям: в ответе должно быть как минимум достаточно контента, чтобы читатели могли составить мнение о том, следует ли переходить по ссылке. И ответ должен иметь смысл даже в автономной копии SE.
typeof(string).GetField("Empty").SetValue(null, " ");
;)public static string Empty { get { return string.Intern(""); } }
?Ответы:
Я могу только предположить здесь:
string.Empty
был определен для явности - при инициализации строки это может быть непонятно из контекста, который""
действительно явно подразумевался как инициализатор (вместоnull
или, скажем," "
или просто как заполнитель во время тестирования). Использованиеstring.Empty
- это определенный ответ на такую головоломку.Это также может быть возврат к C - пустая строка в C не является пустой строкой. Это массив символов, первый символ которого равен нулю (следовательно, пуст), который не совпадает с C #. Я хочу сказать, что в разных языках вы представляете пустую строку по-разному (и они могут иметь разное значение), что
string.Empty
исключает такую двусмысленность.В отличие от того, что другие говорят о множественных объектах - это не проблема, так как любой строковый литерал будет интернирован при компиляции. Это включает в себя значение
string.Empty
-""
. Каждый раз, когда любое из них повторяется в коде, объект будет извлечен из внутреннего пула. Это верно для домена приложения .источник
""
, вы получите{'\0'}
, так что не будет никакой разницы между литералом пустой строки и каким-либо другим окольным способом ее определения.Я не уверен на 100% в источниках, где я их узнал, но некоторые из пунктов его использования включают:
Каждая строка в сборке .NET уникальна, поэтому
приводит к 2 строкам в выходной сборке, так как строки являются неизменяемыми. Наличие обеих ссылок
string.Empty
уменьшает размер сборки.string.Empty
с намерением, становится ясно, что это должна быть пустая строка. Но если вы столкнулись сfoo = ""
тем, что программист удалил содержимое строки во время тестирования и забыл добавить ее обратно, или это должно быть так?источник
""
/string.Empty
интернированы, и будет создан только один объект.Объект не будет создан для
string.Empty
. Использование""
создаст объект, который, скорее всего, будет исходить из пула интернированных строк.В прошлом люди запускали тесты и
String.Empty
выходили чуть быстрее, но это микрооптимизация.String.Empty это:
источник
Это вопрос оптимизации использования памяти и оптимизации сравнения строк. Каждый раз, когда вы используете пустую строку в вашем приложении, вы выделяете строковый объект, содержащий 0 символов. Что касается сравнения строк, это можно сделать, сравнивая ссылки (указатели) вместо символьных, что быстрее даже для пустых строк.
Если вы много раз используете одну и ту же строку в своем приложении, вы можете использовать один и тот же тип механизма, вызывая String.Intern () со своей строкой. Но если вы используете каждую строку только один раз, тогда вы будете использовать только больше памяти.
Так что String.Empty - это только особый вариант оптимизации, который стоит делать для большинства приложений .Net, поэтому он был интегрирован в BCL.
Для более подробной информации по этому вопросу я настоятельно рекомендую прочитать сообщение в блоге Эрика Липперта .
Вы также должны взглянуть на эту документацию, на которую ссылается его блог.
источник