+1: В прошлом я удивлялся, почему компилятор C # не компилировался typeof(string).TypeHandleс ldtokenинструкцией CIL, но похоже, что CLR позаботится об этом в JIT. Требуется еще несколько дополнительных кодов операций, но это более обобщенное применение оптимизации.
Сэм Харвелл
2
Прочтите также Болееloglog.blogspot.ca/2013/09 /… Они проводят повторное тестирование для разных сред и x86 по сравнению с x64 с очень разными результатами.
САПР bloke
1
Обратите внимание, что это верно только для справочных типов. И разница в скорости не так существенна. Учитывая штраф в случае типов значений для GetType, isвсегда является более безопасным выбором, если речь идет о производительности. Конечно, они делают разные вещи.
Nawfal
Если вы поместите это в Resharper, предложите изменить его на «есть»!
Роб Седжвик
@nawfal, я изначально думал, что ваша точка зрения о штрафе в боксе имеет смысл для структурных типов, но, учитывая, что мы тестируем object obj;переменную, разве она уже не упакована, когда это имеет тенденцию проверяться? Есть ли случай, когда вам нужно проверить тип чего-либо, а он еще не упакован как объект?
Роб Паркер
193
Имеет ли значение, что быстрее, если они не делают то же самое? Сравнение производительности утверждений с различным значением кажется плохой идеей.
isговорит вам, реализует ли объект ClassAгде-либо в своем типе heirarchy. GetType()рассказывает о наиболее производном типе.
Это имеет значение, потому что в моем случае я уверен, что они возвращают тот же результат.
ilitirit
37
@ [ilitirit]: они возвращают тот же результат прямо сейчас, но если вы добавите подкласс позже, они не будут
Стивен А. Лоу
13
Оптимизация сейчас сделает ваш код хрупким и сложным в обслуживании.
ICR
9
Мои занятия запечатаны.
ilitirit
26
Они не делают то же самое. Первый работает, если obj имеет тип ClassA или некоторый подкласс ClassA. Второй будет соответствовать только объектам типа ClassA. Второй будет быстрее, так как он не должен проверять иерархию классов.
Для тех, кто хочет знать причину, но не хочет читать статью, на которую ссылаются в это против typeof .
@amitjha Я немного обеспокоен тем, что, поскольку этот тест был запущен под Mono, он не включает JIT-оптимизации, упомянутые в статье. Поскольку статья показывает обратное, на мой взгляд, вопрос открытый. В любом случае, сравнение производительности операций, которые делают разные вещи в зависимости от типа, кажется бесполезным занятием. Используйте операцию, которая соответствует
нужному
16
Я сделал несколько тестов, где они делают то же самое - запечатанные типы.
var c1 ="";var c2 =typeof(string);object oc1 = c1;object oc2 = c2;var s1 =0;var s2 ='.';object os1 = s1;object os2 = s2;bool b =false;Stopwatch sw =Stopwatch.StartNew();for(int i =0; i <10000000; i++){
b = c1.GetType()==typeof(string);// ~60ms
b = c1 isstring;// ~60ms
b = c2.GetType()==typeof(string);// ~60ms
b = c2 isstring;// ~50ms
b = oc1.GetType()==typeof(string);// ~60ms
b = oc1 isstring;// ~68ms
b = oc2.GetType()==typeof(string);// ~60ms
b = oc2 isstring;// ~64ms
b = s1.GetType()==typeof(int);// ~130ms
b = s1 isint;// ~50ms
b = s2.GetType()==typeof(int);// ~140ms
b = s2 isint;// ~50ms
b = os1.GetType()==typeof(int);// ~60ms
b = os1 isint;// ~74ms
b = os2.GetType()==typeof(int);// ~60ms
b = os2 isint;// ~68ms
b =GetType1<string,string>(c1);// ~178ms
b =GetType2<string,string>(c1);// ~94ms
b =Is<string,string>(c1);// ~70ms
b =GetType1<string,Type>(c2);// ~178ms
b =GetType2<string,Type>(c2);// ~96ms
b =Is<string,Type>(c2);// ~65ms
b =GetType1<string,object>(oc1);// ~190ms
b =Is<string,object>(oc1);// ~69ms
b =GetType1<string,object>(oc2);// ~180ms
b =Is<string,object>(oc2);// ~64ms
b =GetType1<int,int>(s1);// ~230ms
b =GetType2<int,int>(s1);// ~75ms
b =Is<int,int>(s1);// ~136ms
b =GetType1<int,char>(s2);// ~238ms
b =GetType2<int,char>(s2);// ~69ms
b =Is<int,char>(s2);// ~142ms
b =GetType1<int,object>(os1);// ~178ms
b =Is<int,object>(os1);// ~69ms
b =GetType1<int,object>(os2);// ~178ms
b =Is<int,object>(os2);// ~69ms}
sw.Stop();MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Универсальные функции для проверки универсальных типов:
staticboolGetType1<S, T>(T t){return t.GetType()==typeof(S);}staticboolGetType2<S, T>(T t){returntypeof(T)==typeof(S);}staticboolIs<S, T>(T t){return t is S;}
Я пробовал и для пользовательских типов, и результаты были последовательными:
var c1 =newClass1();var c2 =newClass2();object oc1 = c1;object oc2 = c2;var s1 =newStruct1();var s2 =newStruct2();object os1 = s1;object os2 = s2;bool b =false;Stopwatch sw =Stopwatch.StartNew();for(int i =0; i <10000000; i++){
b = c1.GetType()==typeof(Class1);// ~60ms
b = c1 isClass1;// ~60ms
b = c2.GetType()==typeof(Class1);// ~60ms
b = c2 isClass1;// ~55ms
b = oc1.GetType()==typeof(Class1);// ~60ms
b = oc1 isClass1;// ~68ms
b = oc2.GetType()==typeof(Class1);// ~60ms
b = oc2 isClass1;// ~68ms
b = s1.GetType()==typeof(Struct1);// ~150ms
b = s1 isStruct1;// ~50ms
b = s2.GetType()==typeof(Struct1);// ~150ms
b = s2 isStruct1;// ~50ms
b = os1.GetType()==typeof(Struct1);// ~60ms
b = os1 isStruct1;// ~64ms
b = os2.GetType()==typeof(Struct1);// ~60ms
b = os2 isStruct1;// ~64ms
b =GetType1<Class1,Class1>(c1);// ~178ms
b =GetType2<Class1,Class1>(c1);// ~98ms
b =Is<Class1,Class1>(c1);// ~78ms
b =GetType1<Class1,Class2>(c2);// ~178ms
b =GetType2<Class1,Class2>(c2);// ~96ms
b =Is<Class1,Class2>(c2);// ~69ms
b =GetType1<Class1,object>(oc1);// ~178ms
b =Is<Class1,object>(oc1);// ~69ms
b =GetType1<Class1,object>(oc2);// ~178ms
b =Is<Class1,object>(oc2);// ~69ms
b =GetType1<Struct1,Struct1>(s1);// ~272ms
b =GetType2<Struct1,Struct1>(s1);// ~140ms
b =Is<Struct1,Struct1>(s1);// ~163ms
b =GetType1<Struct1,Struct2>(s2);// ~272ms
b =GetType2<Struct1,Struct2>(s2);// ~140ms
b =Is<Struct1,Struct2>(s2);// ~163ms
b =GetType1<Struct1,object>(os1);// ~178ms
b =Is<Struct1,object>(os1);// ~64ms
b =GetType1<Struct1,object>(os2);// ~178ms
b =Is<Struct1,object>(os2);// ~64ms}
sw.Stop();MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Вызов GetTypeна structсек медленнее. GetTypeопределяется для objectкласса, который не может быть переопределен в подтипах и, следовательно, structдолжен быть упакован для вызова GetType.
На экземпляре объекта, GetTypeэто быстрее, но очень незначительно.
По универсальному типу, если Tесть class, то isнамного быстрее. Если Tесть struct, то isгораздо быстрее, GetTypeно typeof(T)гораздо быстрее, чем оба. В случаях Tсуществ class, typeof(T)не является надежным , так как его отличается от фактического базового типа t.GetType.
Короче говоря, если у вас есть objectэкземпляр, используйте GetType. Если у вас есть универсальный classтип, используйте is. Если у вас есть универсальный structтип, используйте typeof(T). Если вы не уверены, является ли универсальный тип ссылочным типом или типом значения, используйте is. Если вы хотите всегда соответствовать одному стилю (для закрытых типов), используйте is..
Ответы:
Это должно ответить на этот вопрос, а затем некоторые.
Вторая строка
if (obj.GetType() == typeof(ClassA)) {}
быстрее для тех, кто не хочет читать статью.(Помните, что они не делают то же самое)
источник
typeof(string).TypeHandle
сldtoken
инструкцией CIL, но похоже, что CLR позаботится об этом в JIT. Требуется еще несколько дополнительных кодов операций, но это более обобщенное применение оптимизации.GetType
,is
всегда является более безопасным выбором, если речь идет о производительности. Конечно, они делают разные вещи.object obj;
переменную, разве она уже не упакована, когда это имеет тенденцию проверяться? Есть ли случай, когда вам нужно проверить тип чего-либо, а он еще не упакован как объект?Имеет ли значение, что быстрее, если они не делают то же самое? Сравнение производительности утверждений с различным значением кажется плохой идеей.
is
говорит вам, реализует ли объектClassA
где-либо в своем типе heirarchy.GetType()
рассказывает о наиболее производном типе.Не то же самое.
источник
Они не делают то же самое. Первый работает, если obj имеет тип ClassA или некоторый подкласс ClassA. Второй будет соответствовать только объектам типа ClassA. Второй будет быстрее, так как он не должен проверять иерархию классов.
Для тех, кто хочет знать причину, но не хочет читать статью, на которую ссылаются в это против typeof .
источник
Я сделал несколько тестов, где они делают то же самое - запечатанные типы.
Универсальные функции для проверки универсальных типов:
Я пробовал и для пользовательских типов, и результаты были последовательными:
И типы:
Умозаключение:
Вызов
GetType
наstruct
сек медленнее.GetType
определяется дляobject
класса, который не может быть переопределен в подтипах и, следовательно,struct
должен быть упакован для вызоваGetType
.На экземпляре объекта,
GetType
это быстрее, но очень незначительно.По универсальному типу, если
T
естьclass
, тоis
намного быстрее. ЕслиT
естьstruct
, тоis
гораздо быстрее,GetType
ноtypeof(T)
гораздо быстрее, чем оба. В случаяхT
существclass
,typeof(T)
не является надежным , так как его отличается от фактического базового типаt.GetType
.Короче говоря, если у вас есть
object
экземпляр, используйтеGetType
. Если у вас есть универсальныйclass
тип, используйтеis
. Если у вас есть универсальныйstruct
тип, используйтеtypeof(T)
. Если вы не уверены, является ли универсальный тип ссылочным типом или типом значения, используйтеis
. Если вы хотите всегда соответствовать одному стилю (для закрытых типов), используйтеis
..источник