対typeof


回答:


167

これはその質問に答えるはずです。

2行目if (obj.GetType() == typeof(ClassA)) {}は、記事を読みたくない人のために高速です。

(彼らは同じことをしないことに注意してください)


1
1:過去にはC#コンパイラはコンパイルできませんでしたなぜ私が疑問に思ったtypeof(string).TypeHandleldtokenCIL命令が、CLRはJITでそれの世話をするように見えます。それでもいくつかの追加のオペコードが必要ですが、最適化のより一般化されたアプリケーションです。
Sam Harwell

2
higherlogics.blogspot.ca/2013/09/…も読んでください-彼らは異なるフレームワークとx86とx64を再テストし、結果が大きく異なります。
CADは2014

1
これは参照型にのみ当てはまることに注意してください。速度の違いはそれほど重要ではありません。以下のための値型の場合はボクシングのペナルティが与えられGetTypeis常に限りのパフォーマンスに関しては、より安全な選択肢です。もちろん、彼らは異なることをします。
nawfal 14

あなたがそれをResharperに入れたら、それを「is」に変更することを提案します!
Rob Sedgwick、2015年

@nawfal、最初はボクシングのペナルティについてのあなたのポイントは構造体型に対して理にかなっていると思いましたが、object obj;変数をテストしているので、これがテストされる傾向にあるときはすでにボックス化されていませんか?何かのタイプをテストする必要があり、まだオブジェクトとしてボックス化されていない場合はありますか?
Rob Parker、

193

彼らが同じことをしなければ、どちらがより速いかは重要ですか?異なる意味を持つステートメントのパフォーマンスを比較することは悪い考えのようです。

isオブジェクトClassAが型階層のどこかに実装しているかどうかを示します。 GetType()最も派生したタイプについて説明します。

同じではありません。


7
私の場合、彼らは同じ結果を返すので、私は前向きだからです。
イリリット2008年

37
@ [ilitirit]:現在同じ結果を返しますが、後でサブクラスを追加しても返されません
Steven A. Lowe

13
今最適化すると、コードが脆弱になり、保守が困難になります。
ICR

9
私のクラスは封印されています。
ilitirit 2008年

26

彼らは同じことをしません。最初のものは、objがClassAタイプまたはClassAのサブクラスである場合に機能します。2つ目は、ClassAタイプのオブジェクトのみに一致します。2番目のクラスは、クラス階層をチェックする必要がないため、より高速になります。

理由を知りたいが、で参照された記事を読みたくない人のために is vs typeofです。


1
@amitjhaこのテストはMonoで実行されたため、記事で参照されているJIT最適化が含まれていないことに少し心配しています。記事は反対を示しているので、私の心の中で質問はオープンなものです。いずれにしても、タイプによって異なる処理を実行する操作のパフォーマンスを比較することは、価値のないことのように思えます。「より高速な」操作ではなく、必要な動作に一致する操作を使用してください
tvanfosson

16

私はそれらが同じことをするいくつかのベンチマークをしました-密封されたタイプ。

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 { }

推論:

  1. 呼び出しGetTypestructSは遅くなります。 サブタイプでオーバーライドできないクラスでGetType定義されているため、を呼び出すにはボックス化する必要があります。objectstructGetType

  2. オブジェクトインスタンスでGetTypeは、より高速ですが、ごくわずかです。

  3. 場合は、一般的なタイプで、Tであるclass、そして、isはるかに高速です。場合Tstructは、isはるかに高速よりGetTypeますがtypeof(T)はるかに高速の両方を超えています。ケースでTあることclasstypeof(T)実際の基になる型からの異なるので、信頼性がありませんt.GetType

つまり、objectインスタンスがある場合は、を使用しますGetType。ジェネリックclass型がある場合は、を使用してくださいis。ジェネリックstruct型がある場合は、を使用してくださいtypeof(T)。ジェネリック型が参照型か値型かわからない場合は、を使用してくださいis。常に1つのスタイルに一致させたい場合(シールされたタイプの場合)、is..を使用します。


1
実際には、まったく気にしないでください。最も意味のあるものを使用してください。
nawfal
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.