これらのコードのうち、どれがより高速ですか?
if (obj is ClassA) {}
if (obj.GetType() == typeof(ClassA)) {}
編集:彼らが同じことをしていないことは承知しています。
彼らが同じことをしなければ、どちらが速いかは重要ですか?異なる意味を持つステートメントのパフォーマンスを比較することは悪い考えのように思われます。
is
ClassA
オブジェクトがその型階層 のどこかに実装されているかどうかを示します。GetType()
最も派生したタイプについて説明します。
同じことではありません。
if (obj.GetType() == typeof(ClassA)) {}
記事を読みたくない人のために、2行目はより高速です。
(彼らは同じことをしないことに注意してください)
彼らは同じことをしません。最初のものは、objがClassAタイプまたはClassAのサブクラスである場合に機能します。2つ目は、ClassAタイプのオブジェクトにのみ一致します。2つ目は、クラス階層をチェックする必要がないため、より高速になります。
理由を知りたいが、で参照されている記事を読みたくない人のためにはvstypeofです。
私は彼らが同じことをするところでいくつかのベンチマークを行いました - 封印されたタイプ。
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 { }
推論:
s の呼び出しGetType
はstruct
遅くなります。 サブタイプでオーバーライドできないクラスでGetType
定義されているため、 を呼び出すにはボックス化する必要があります。object
struct
GetType
オブジェクト インスタンスでGetType
は、高速ですが、ごくわずかです。
ジェネリック型でT
はclass
、 is の場合、is
はるかに高速です。T
がの場合struct
、is
は よりもはるかに高速ですGetType
がtypeof(T)
、両方よりもはるかに高速です。の場合、実際の基T
になる型とは異なるため、信頼できません。class
typeof(T)
t.GetType
つまり、object
インスタンスがある場合は、 を使用しますGetType
。class
ジェネリック型がある場合は、 を使用しますis
。struct
ジェネリック型がある場合は、 を使用しますtypeof(T)
。ジェネリック型が参照型か値型か不明な場合は、 を使用してis
ください。常に 1 つのスタイルに一貫性を持たせたい場合 (封印された型の場合)、is
..