Відповіді:
Це повинно відповісти на це питання, а потім на деякі.
Другий рядок, if (obj.GetType() == typeof(ClassA)) {}
швидше, для тих, хто не хоче читати статтю.
(Будьте в курсі, що вони не роблять те саме)
typeof(string).TypeHandle
в ldtoken
інструкції CIL, але схоже , що CLR піклується про нього в JIT. Це все ще потребує декількох додаткових опкодів, але це більш узагальнене застосування оптимізації.
GetType
, is
це завжди більш безпечний вибір щодо продуктивності. Звичайно, вони роблять різні речі.
object obj;
змінну, чи не є вона вже в коробці, коли це, як правило, тестується? Чи є випадок, коли вам потрібно протестувати тип чогось, і це вже не є об'єктом?
Чи важливо, що швидше, якщо вони не роблять те саме? Порівнювати виконання тверджень із різним значенням видається поганою ідеєю.
is
повідомляє вам, чи об’єкт реалізує ClassA
десь у своїй герархії типу. GetType()
розповідає про найбільш похідний тип.
Не те саме.
Вони не роблять те саме. Перший працює, якщо obj має тип ClassA або якогось підкласу ClassA. Друга відповідатиме лише об’єктам типу ClassA. Другий буде швидшим, оскільки не потрібно перевіряти ієрархію класів.
Для тих, хто хоче знати причину, але не хоче читати статтю, на яку йдеться є vs 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
s проходить повільніше. 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
..