+1: No passado, eu me perguntava por que o compilador C # não foi compilado typeof(string).TypeHandlecom a ldtokeninstrução CIL, mas parece que o CLR cuida disso no JIT. Ainda são necessários alguns códigos de operação extras, mas é uma aplicação mais generalizada da otimização.
Observe que isso é verdade apenas para tipos de referência. E a diferença de velocidade não é tão significativa. Dada a penalidade de boxe em caso de tipos de valor GetType, isé sempre uma escolha mais segura no que diz respeito ao desempenho. Claro que eles fazem coisas diferentes.
Nawfal 4/08
Se você colocar isso no Resharper, sugira alterá-lo para "é"!
Rob Sedgwick
@awawfal, inicialmente pensei que seu ponto sobre a penalidade de boxe fazia sentido para os tipos de estruturas, mas, como estamos testando uma object obj;variável, ela já não está encaixotada quando isso tende a ser testado? Existe um caso em que você precisa testar o tipo de algo e ele ainda não está na caixa como um objeto?
22420 Robbie Parker
193
Importa o que é mais rápido, se eles não fazem a mesma coisa? Comparar o desempenho de declarações com diferentes significados parece uma má ideia.
isinforma se o objeto implementa ClassAem qualquer lugar da hierarquia de tipos. GetType()informa sobre o tipo mais derivado.
Importa, porque no meu caso, tenho certeza de que eles retornam o mesmo resultado.
Ilitirit 8/10/08
37
@ [ilitirit]: eles retornam o mesmo resultado agora, mas se você adicionar uma subclasse mais tarde, eles não serão
Steven A. Lowe
13
A otimização agora tornará seu código frágil e difícil de manter.
ICR
9
Minhas aulas são seladas.
Ilitirit 10/10/08
26
Eles não fazem a mesma coisa. O primeiro funciona se obj for do tipo ClassA ou de alguma subclasse da ClassA. O segundo corresponderá apenas a objetos do tipo ClassA. O segundo será mais rápido, pois não precisa verificar a hierarquia de classes.
Para quem quer saber o motivo, mas não quer ler o artigo mencionado em é vs typeof .
@amitjha Estou um pouco preocupado que, porque esse teste foi executado no Mono, ele não inclui as otimizações de JIT mencionadas no artigo. Como o artigo mostra o contrário, na minha opinião a questão é aberta. De qualquer forma, comparar o desempenho de operações que fazem coisas diferentes, dependendo do tipo, parece um exercício inútil. Use a operação que corresponde ao comportamento que você precisa, não o que é "mais rápido"
tvanfosson
16
Fiz alguns testes comparativos onde eles fazem os mesmos tipos selados.
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());
As funções genéricas para testar tipos genéricos:
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;}
Tentei também tipos personalizados e os resultados foram consistentes:
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());
Chamando GetTypeem structs é mais lento. GetTypeé definido na objectclasse que não pode ser substituída em subtipos e, portanto, structprecisa ser encaixotada para ser chamada GetType.
Em uma instância de objeto, GetTypeé mais rápido, mas muito marginalmente.
No tipo genérico, se Tfor class, então isé muito mais rápido. Se Tfor struct, então isé muito mais rápido que, GetTypemas typeof(T)é muito mais rápido que ambos. Nos casos de Tser class, typeof(T)não é confiável, pois é diferente do tipo subjacente real t.GetType.
Em resumo, se você tiver uma objectinstância, use GetType. Se você tem um classtipo genérico , use is. Se você tem um structtipo genérico , use typeof(T). Se você não tiver certeza se o tipo genérico é o tipo de referência ou o valor, use is. Se você quiser sempre ser consistente com um estilo (para tipos selados), use is..
Respostas:
Isso deve responder a essa pergunta e mais algumas.
A segunda linha
if (obj.GetType() == typeof(ClassA)) {}
,, é mais rápida, para aqueles que não querem ler o artigo.(Esteja ciente de que eles não fazem a mesma coisa)
fonte
typeof(string).TypeHandle
com aldtoken
instrução CIL, mas parece que o CLR cuida disso no JIT. Ainda são necessários alguns códigos de operação extras, mas é uma aplicação mais generalizada da otimização.GetType
,is
é sempre uma escolha mais segura no que diz respeito ao desempenho. Claro que eles fazem coisas diferentes.object obj;
variável, ela já não está encaixotada quando isso tende a ser testado? Existe um caso em que você precisa testar o tipo de algo e ele ainda não está na caixa como um objeto?Importa o que é mais rápido, se eles não fazem a mesma coisa? Comparar o desempenho de declarações com diferentes significados parece uma má ideia.
is
informa se o objeto implementaClassA
em qualquer lugar da hierarquia de tipos.GetType()
informa sobre o tipo mais derivado.Não é a mesma coisa.
fonte
Eles não fazem a mesma coisa. O primeiro funciona se obj for do tipo ClassA ou de alguma subclasse da ClassA. O segundo corresponderá apenas a objetos do tipo ClassA. O segundo será mais rápido, pois não precisa verificar a hierarquia de classes.
Para quem quer saber o motivo, mas não quer ler o artigo mencionado em é vs typeof .
fonte
Fiz alguns testes comparativos onde eles fazem os mesmos tipos selados.
As funções genéricas para testar tipos genéricos:
Tentei também tipos personalizados e os resultados foram consistentes:
E os tipos:
Inferência:
Chamando
GetType
emstruct
s é mais lento.GetType
é definido naobject
classe que não pode ser substituída em subtipos e, portanto,struct
precisa ser encaixotada para ser chamadaGetType
.Em uma instância de objeto,
GetType
é mais rápido, mas muito marginalmente.No tipo genérico, se
T
forclass
, entãois
é muito mais rápido. SeT
forstruct
, entãois
é muito mais rápido que,GetType
mastypeof(T)
é muito mais rápido que ambos. Nos casos deT
serclass
,typeof(T)
não é confiável, pois é diferente do tipo subjacente realt.GetType
.Em resumo, se você tiver uma
object
instância, useGetType
. Se você tem umclass
tipo genérico , useis
. Se você tem umstruct
tipo genérico , usetypeof(T)
. Se você não tiver certeza se o tipo genérico é o tipo de referência ou o valor, useis
. Se você quiser sempre ser consistente com um estilo (para tipos selados), useis
..fonte