String.Empty
От: 4mbi3nt http://esud.info
Дата: 17.12.03 21:48
Оценка:
Я помню что когдато в книжке читал, что string переменные рекомендуется
проверять на String.Empty а не на "" или null как некоторые делают. А если string
имеет значение null, то по идеи String.Empty его тоже должен отлавливать. Вот в этом примере этого не происходит:


string s = null;

if(s == String.Empty)
{
   Console.WriteLine("empty");
}
else
{
   Console.WriteLine("not empty");
}



Это глюк C#? ...или посоветуйте мне как надо по другому проверять значения
esud.info
Re: String.Empty
От: trialex  
Дата: 17.12.03 22:09
Оценка: 10 (1)
Здравствуйте, 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а.
Re[2]: String.Empty
От: Воронков Василий Россия  
Дата: 17.12.03 22:19
Оценка: -2
Здравствуйте, trialex, Вы писали:

T>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.


Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.

Это как я себе это представляю.
... << RSDN@Home 1.1.2 beta 1 >>
Re[2]: String.Empty
От: trialex  
Дата: 17.12.03 22:20
Оценка:
Так, есс-но тоже можно
if (s == null || s == "")
{
    Console.WriteLine("empty");
}
else
{
    Console.WriteLine("not empty");
}
Re[3]: String.Empty
От: trialex  
Дата: 17.12.03 22:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, trialex, Вы писали:


T>>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.


ВВ>Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.


ВВ>Это как я себе это представляю.


А если приплюсовать сюда общий strings table, то не так страшен черт... Можно посмотреть что JIT сделает в двух случаях...
Re[3]: String.Empty
От: SiAVoL Россия  
Дата: 18.12.03 06:15
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, trialex, Вы писали:


T>>Не думаю что есть разница в сравнении к "" и String.Empty после JITа.


ВВ>Думаю, что разница есть. Т.к. строка это ссылочный тип, что используя сравнение с "", ты тем самым каждый раз создаешь новый объект — пустую строку. А String.Empty — это что-то вроде объекта-синглтона, соответственно объект каждый раз не создается. (А оператор сравнения там явно перегружен). Поэтому String.Empty должен быть просто более производительным.


ВВ>Это как я себе это представляю.


Насколько я помню оптимизатор шарпа выцепляет все одинаковые строки в коде и на каждую из них создает по одному экземпляру string. В случае с "" он возможно заменяет на string.Empty, но надо бы проверить
... << RSDN@Home 1.1.2 beta 2 >>
Re[3]: String.Empty
От: Yury_Malich Германия http://malich.ru
Дата: 18.12.03 06:34
Оценка: 10 (2)
ВВ>Это как я себе это представляю.

А вот что пишет Рихтер.

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.

И в этом легко убедится написав

bool b=Object.ReferenceEquals(String.Empty, "");

Чему равно b? Конечно же true
"Практика — критерий истины" (c) Маркс
Re[4]: String.Empty
От: Igor Trofimov  
Дата: 18.12.03 06:58
Оценка: +1
SAV>Насколько я помню оптимизатор шарпа выцепляет все одинаковые строки в коде и на каждую из них создает по одному экземпляру string. В случае с "" он возможно заменяет на string.Empty, но надо бы проверить

Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.
Re[5]: String.Empty
От: nogtol  
Дата: 18.12.03 08:21
Оценка: +2
А как насчет
if( str!= null && str.Length !=0 )
{
// do smth
}
Re[6]: String.Empty
От: Алексей Одинцов Россия  
Дата: 18.12.03 09:42
Оценка:
Здравствуйте, nogtol, Вы писали:

N>А как насчет

N>if( str!= null && str.Length !=0 )
N>{
N>// do smth
N>}

это известная рекомендация, типа оптимизация производительности... FxCop даже ругается если так не делать
... << RSDN@Home 1.1.0 stable >>
Re: String.Empty
От: Аноним  
Дата: 18.12.03 11:38
Оценка:
Здравствуйте, 4mbi3nt, Вы писали:

4>Это глюк C#? ...




Нет, это глюк книжки.

string s = null;

if(s == null || s == string.Empty)
{
   Console.WriteLine("empty");
}
else
{
   Console.WriteLine("not empty");
}
Re[5]: String.Empty
От: Lloyd Россия  
Дата: 18.12.03 12:38
Оценка:
Здравствуйте, 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
            //
        }
    }
}
... << RSDN@Home 1.1.2 beta 1 >>
Re[6]: String.Empty
От: orangy Россия
Дата: 18.12.03 12:47
Оценка:
Здравствуйте, Lloyd, Вы писали:

iT>>Тут даже не в компиляторе дело, а в рантайме (интернирование строк). Не важно, кто создается раньше — "" или string.Empty — в результате они будут указывать на одну и ту же строку, поскольку строки одинаковые.


L>Неправда твоя.

Неправда относительная. Речь шла во-первых о константных строках. Во-вторых, во многих случаях компилятор создаёт интернирующий код, например в случае switch по строке.
... << RSDN@Home 1.1.2 beta 2 >>
"Develop with pleasure!"
Re[6]: String.Empty
От: trialex  
Дата: 18.12.03 15:18
Оценка:
Здравствуйте, 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)

 [0000] push        esi
 [0001] mov         ecx,dword ptr ds:[05A4202Ch]
 [0007] mov         edx,dword ptr ds:[05A410C8h]
 [000d] mov         eax,dword ptr [ecx]
 [000f] call        dword ptr [eax+000000D8h]
 [0015] mov         esi,dword ptr ds:[05A410CCh]


 [001b] mov         edx,dword ptr ds:[05A41038h]
 [0021] mov         ecx,esi
 [0023] call        dword ptr ds:[79BF9C28h]
 [0029] test        eax,eax
 [002b] jne         00000012
 [002d] mov         ecx,dword ptr ds:[05A4202Ch]
 [0033] mov         edx,esi
 [0035] mov         eax,dword ptr [ecx]
 [0037] call        dword ptr [eax+000000D8h]

 [003d] mov         edx,dword ptr ds:[05A42010h]
 [0043] mov         ecx,esi
 [0045] call        dword ptr ds:[79BF9C28h]
 [004b] test        eax,eax
 [004d] sete        al
 [0050] movzx       eax,al
 [0053] test        eax,eax
 [0055] je          00000012
 [0057] mov         ecx,dword ptr ds:[05A4202Ch]
 [005d] mov         edx,esi
 [005f] mov         eax,dword ptr [ecx]
 [0061] call        dword ptr [eax+000000D8h]

 [0067] mov         edx,dword ptr ds:[05A41038h]
 [006d] mov         ecx,esi
 [006f] call        dword ptr ds:[79BF9C28h]
 [0075] test        eax,eax
 [0077] jne         00000012
 [0079] mov         ecx,dword ptr ds:[05A4202Ch]
 [007f] mov         edx,esi
 [0081] mov         eax,dword ptr [ecx]
 [0083] call        dword ptr [eax+000000D8h]
 [0089] pop         esi
 [008a] ret


Вот собственно загрузка пустой строки для сравнения:

Первый s != "":        [001b] mov         edx,dword ptr ds:[05A41038h]
s != String.Empty:     [003d] mov         edx,dword ptr ds:[05A42010h]
Второй s != "":        [0067] mov         edx,dword ptr ds:[05A41038h]



Так вот, значение по ds:[05A41038h] и по ds:[05A42010h] одинаковое — адрес размещения пустой строки.

Почему инструкции для String.Empty слегка отличаются — для меня загадка.
Re[6]: String.Empty
От: trialex  
Дата: 18.12.03 15:25
Оценка:
Здравствуйте, nogtol, Вы писали:

N>А как насчет

N>if( str!= null && str.Length !=0 )
N>{
N>// do smth
N>}

В условии задачи спрашивали про String.Empty Этот метод конечно быстрее всего.
Re[7]: String.Empty
От: Igor Trofimov  
Дата: 18.12.03 15:53
Оценка:
T>Почему инструкции для String.Empty слегка отличаются — для меня загадка.

Может дело в том, что Empty — это поле?

Вот если в рантайм двумя разными способами получить пустую строку — они будут совпадать? Будут совпадать с заданной прямо в коде константой ""?
Re[8]: String.Empty
От: trialex  
Дата: 18.12.03 16:04
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

T>>Почему инструкции для String.Empty слегка отличаются — для меня загадка.


iT>Может дело в том, что Empty — это поле?


iT>Вот если в рантайм двумя разными способами получить пустую строку — они будут совпадать? Будут совпадать с заданной прямо в коде константой ""?


Моя твоя не понимать
Но ответ наверное да
Re[7]: String.Empty
От: mihailik Украина  
Дата: 18.12.03 16:18
Оценка: 2 (2)
АО>это известная рекомендация, типа оптимизация производительности... FxCop даже ругается если так не делать

И зря, наверное ругается. Производительность пусть компилятор с JIT'ом оптимизируют. Вот уж кого не перехитришь.

А простым программерам лучше тратить силы на читабельность и прозрачность программ. Сравнение с пустой строкой выглядит однозначно прозрачнее и Length и String.Empty.
... << RSDN@Home 1.1.0 stable >>
Re[4]: String.Empty
От: Igor Trofimov  
Дата: 18.12.03 17:07
Оценка:
Вот именно об этом я и говорил.. Что по идее это заслуга рантаймового механизма интернирования...

Но вот у товарища Lloyd не получается равенство ;(
Re[4]: String.Empty
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 18.12.03 17:17
Оценка:
Здравствуйте, 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>
Y_M>bool b=Object.ReferenceEquals(String.Empty, "");
Y_M>

Y_M>Чему равно b? Конечно же true

Вы немного путаете Глобальную хэшТаблицу, в которую попадают константы, а также при методе
String.Internal. Проверкой служит IsInternal. Но если вы хотите из нее делать свалку то используйте
S=String.Internal(); Но Empty это статическое поле и не факт, что будет ссылаться на адрес "" в хэштаблице.
http://www.rsdn.ru/Forum/Message.aspx?mid=483245&amp;only=1
Автор: trialex
Дата: 18.12.03
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.