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)
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.
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.
isinforma se o objeto implementa ClassAem qualquer lugar da hierarquia de tipos. GetType()informa sobre o tipo mais derivado.
Não é a mesma coisa.
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 .
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 is string; // ~60ms
b = c2.GetType() == typeof(string); // ~60ms
b = c2 is string; // ~50ms
b = oc1.GetType() == typeof(string); // ~60ms
b = oc1 is string; // ~68ms
b = oc2.GetType() == typeof(string); // ~60ms
b = oc2 is string; // ~64ms
b = s1.GetType() == typeof(int); // ~130ms
b = s1 is int; // ~50ms
b = s2.GetType() == typeof(int); // ~140ms
b = s2 is int; // ~50ms
b = os1.GetType() == typeof(int); // ~60ms
b = os1 is int; // ~74ms
b = os2.GetType() == typeof(int); // ~60ms
b = os2 is int; // ~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:
static bool GetType1<S, T>(T t)
{
return t.GetType() == typeof(S);
}
static bool GetType2<S, T>(T t)
{
return typeof(T) == typeof(S);
}
static bool Is<S, T>(T t)
{
return t is S;
}
Tentei também tipos personalizados e os resultados foram consistentes:
var c1 = new Class1();
var c2 = new Class2();
object oc1 = c1;
object oc2 = c2;
var s1 = new Struct1();
var s2 = new Struct2();
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 is Class1; // ~60ms
b = c2.GetType() == typeof(Class1); // ~60ms
b = c2 is Class1; // ~55ms
b = oc1.GetType() == typeof(Class1); // ~60ms
b = oc1 is Class1; // ~68ms
b = oc2.GetType() == typeof(Class1); // ~60ms
b = oc2 is Class1; // ~68ms
b = s1.GetType() == typeof(Struct1); // ~150ms
b = s1 is Struct1; // ~50ms
b = s2.GetType() == typeof(Struct1); // ~150ms
b = s2 is Struct1; // ~50ms
b = os1.GetType() == typeof(Struct1); // ~60ms
b = os1 is Struct1; // ~64ms
b = os2.GetType() == typeof(Struct1); // ~60ms
b = os2 is Struct1; // ~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());
E os tipos:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Inferência:
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..