Respuestas:
Esto debería responder esa pregunta, y algo más.
La segunda línea, if (obj.GetType() == typeof(ClassA)) {}es más rápida, para aquellos que no quieren leer el artículo.
(Tenga en cuenta que no hacen lo mismo)
typeof(string).TypeHandlela ldtokeninstrucción CIL, pero parece que el CLR se encarga de eso en el JIT. Todavía requiere algunos códigos de operación adicionales, pero es una aplicación más generalizada de la optimización.
GetType, issiempre es una opción más segura en lo que respecta al rendimiento. Por supuesto que hacen cosas diferentes.
object obj;variable, ¿no está ya encuadrada cuando esto tiende a probarse? ¿Hay algún caso en el que necesites probar el tipo de algo y aún no esté encuadrado como un objeto?
¿Importa cuál es más rápido si no hacen lo mismo? Comparar el desempeño de las declaraciones con diferentes significados parece una mala idea.
isle indica si el objeto se implementa ClassAen algún lugar de su jerarquía de tipos. GetType()le informa sobre el tipo más derivado.
No es lo mismo.
No hacen lo mismo. El primero funciona si obj es de tipo ClassA o de alguna subclase de ClassA. El segundo solo coincidirá con objetos de tipo ClassA. El segundo será más rápido ya que no tiene que verificar la jerarquía de clases.
Para aquellos que quieren saber la razón, pero no quieren leer el artículo al que se hace referencia en es vs typeof .
Hice algunas evaluaciones comparativas donde hacen lo mismo: tipos sellados.
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());
Las funciones genéricas para probar los 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;
}
También probé los tipos personalizados y los resultados fueron 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());
Y los tipos:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Inferencia:
Llamar GetTypea structs es más lento. GetTypese define en una objectclase que no se puede anular en subtipos y, por lo tanto, se structdebe encuadrar para poder llamar GetType.
En una instancia de objeto, GetTypees más rápido, pero muy marginal.
En el tipo genérico, si Tes class, entonces ises mucho más rápido. Si Tes así struct, entonces ises mucho más rápido que, GetTypepero typeof(T)es mucho más rápido que ambos. En casos de Tser class, typeof(T)no es confiable ya que es diferente del tipo subyacente real t.GetType.
En resumen, si tiene una objectinstancia, use GetType. Si tiene un classtipo genérico , use is. Si tiene un structtipo genérico , use typeof(T). Si no está seguro si el tipo genérico es tipo de referencia o tipo de valor, use is. Si quiere ser consistente con un estilo siempre (para tipos sellados), use is...