Відповіді:
Це повинно відповісти на це питання, а потім на деякі.
Другий рядок, 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на structs проходить повільніше. 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..