Я помню что когдато в книжке читал, что string переменные рекомендуется
проверять на String.Empty а не на "" или null как некоторые делают. А если string
имеет значение null, то по идеи String.Empty его тоже должен отлавливать. Вот в этом примере этого не происходит:
Здравствуйте, 4mbi3nt, Вы писали:
4>Я помню что когдато в книжке читал, что string переменные рекомендуется 4>проверять на String.Empty а не на "" или null как некоторые делают. А если string 4>имеет значение null, то по идеи String.Empty его тоже должен отлавливать. Вот в этом примере этого не происходит:
4>Это глюк C#? ...или посоветуйте мне как надо по другому проверять значения
The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables.
String.Empty Field
The value of this field is the zero-length string, "".
null != "", все верно.
Проверяй так:
string s = null;
if (s != null && s != "")
{
Console.WriteLine("not empty");
}
else
{
Console.WriteLine("empty");
}
Не думаю что есть разница в сравнении к "" и String.Empty после JITа.
Здравствуйте, trialex, Вы писали:
T>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.
Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, trialex, Вы писали:
T>>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.
ВВ>Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.
ВВ>Это как я себе это представляю.
А если приплюсовать сюда общий strings table, то не так страшен черт... Можно посмотреть что JIT сделает в двух случаях...
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, trialex, Вы писали:
T>>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.
ВВ>Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.
ВВ>Это как я себе это представляю.
Насколько я помню оптимизатор шарпа выцепляет все одинаковые строки в коде и на каждую из них создает по одному экземпляру string. В случае с "" он возможно заменяет на string.Empty, но надо бы проверить
When the CLR initializes, it creates an internal hash table in which the keys are strings and
the values are references to string objects in the managed heap. Initially, the table is empty
(of course). When the JIT compiler compiles this method, it looks up each literal string in the
hash table. The compiler looks for the first “Hello” string and because it doesn’t find one,
constructs a new String object in the managed heap (that refers to this string) and adds
the "Hello" String and a reference to the object into the hash table. Then the JIT compiler
looks up the second "Hello" string in the hash table. It finds this string, so nothing happens.
Because there are no more literal strings in the code, the code can now execute.
SAV>Насколько я помню оптимизатор шарпа выцепляет все одинаковые строки в коде и на каждую из них создает по одному экземпляру string. В случае с "" он возможно заменяет на string.Empty, но надо бы проверить
Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.
Здравствуйте, Igor Trofimov, Вы писали:
iT>Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.
Неправда твоя.
using System;
namespace StringTest
{
/// <summary>
/// Summary description for Class1.
/// </summary>class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
string s1 = new string('-', 0);//Получили ""string s2 = string.Empty;//Получили второй ""
Console.WriteLine(object.ReferenceEquals(s1, s2));//Убедились что это разные объекты. ;) return;
//
// TODO: Add code to start application here
//
}
}
}
Здравствуйте, Lloyd, Вы писали:
iT>>Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.
L>Неправда твоя.
Неправда относительная. Речь шла во-первых о константных строках. Во-вторых, во многих случаях компилятор создаёт интернирующий код, например в случае switch по строке.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, Igor Trofimov, Вы писали:
iT>>Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.
L>Неправда твоя.
Правда, неправда, нерпавда, правда
using System;
class EmptyVsNull
{
static void Main(string[] args)
{
string s = null;
Console.WriteLine("start");
s = "some string";
if (s != "") Console.WriteLine(s);
if (s != String.Empty) Console.WriteLine(s);
if (s != "") Console.WriteLine(s);
}
}
cordbg для Main выдал следущее (JitOptimizations=1)
Здравствуйте, Igor Trofimov, Вы писали:
T>>Почему инструкции для String.Empty слегка отличаются — для меня загадка.
iT>Может дело в том, что Empty — это поле?
iT>Вот если в рантайм двумя разными способами получить пустую строку — они будут совпадать? Будут совпадать с заданной прямо в коде константой ""?
АО>это известная рекомендация, типа оптимизация производительности... FxCop даже ругается если так не делать
И зря, наверное ругается. Производительность пусть компилятор с JIT'ом оптимизируют. Вот уж кого не перехитришь.
А простым программерам лучше тратить силы на читабельность и прозрачность программ. Сравнение с пустой строкой выглядит однозначно прозрачнее и Length и String.Empty.
Здравствуйте, Yury_Malich, Вы писали:
ВВ>>Это как я себе это представляю.
Y_M>А вот что пишет Рихтер.
Y_M>When the CLR initializes, it creates an internal hash table in which the keys are strings and Y_M>the values are references to string objects in the managed heap. Initially, the table is empty Y_M>(of course). When the JIT compiler compiles this method, it looks up each literal string in the Y_M>hash table. The compiler looks for the first “Hello” string and because it doesn’t find one, Y_M>constructs a new String object in the managed heap (that refers to this string) and adds Y_M>the "Hello" String and a reference to the object into the hash table. Then the JIT compiler Y_M>looks up the second "Hello" string in the hash table. It finds this string, so nothing happens. Y_M>Because there are no more literal strings in the code, the code can now execute.
Y_M>И в этом легко убедится написав
Y_M>
Вы немного путаете Глобальную хэшТаблицу, в которую попадают константы, а также при методе
String.Internal. Проверкой служит IsInternal. Но если вы хотите из нее делать свалку то используйте
S=String.Internal(); Но Empty это статическое поле и не факт, что будет ссылаться на адрес "" в хэштаблице. http://www.rsdn.ru/Forum/Message.aspx?mid=483245&only=1