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).TypeHandle
la ldtoken
instrucció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
, is
siempre 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.
is
le indica si el objeto se implementa ClassA
en 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 GetType
a struct
s es más lento. GetType
se define en una object
clase que no se puede anular en subtipos y, por lo tanto, se struct
debe encuadrar para poder llamar GetType
.
En una instancia de objeto, GetType
es más rápido, pero muy marginal.
En el tipo genérico, si T
es class
, entonces is
es mucho más rápido. Si T
es así struct
, entonces is
es mucho más rápido que, GetType
pero typeof(T)
es mucho más rápido que ambos. En casos de T
ser class
, typeof(T)
no es confiable ya que es diferente del tipo subyacente real t.GetType
.
En resumen, si tiene una object
instancia, use GetType
. Si tiene un class
tipo genérico , use is
. Si tiene un struct
tipo 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
...