Ответы:
Это должно ответить на этот вопрос, а затем некоторые.
Вторая строка 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 .
Я сделал несколько тестов, где они делают то же самое - запечатанные типы.
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());
Универсальные функции для проверки универсальных типов:
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;
}
Я пробовал и для пользовательских типов, и результаты были последовательными:
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());
И типы:
sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }
Умозаключение:
Вызов 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
..