2008-10-08 62 views
118

哪些代碼段速度更快?與typeof

if (obj is ClassA) {} 

if (obj.GetType() == typeof(ClassA)) {} 

編輯: 我知道他們不這樣做。

+1

在這裏回答了類似的問題:http://stackoverflow.com/questions/57701/what-are-the-performance-characteristics c#57713 – swilliams 2008-10-08 20:21:56

回答

142

This should answer that question, and then some.

第二行,if (obj.GetType() == typeof(ClassA)) {},速度更快,對於那些不想讀文章。

+1

+1:在過去,我想知道爲什麼C#編譯器沒有將`typeof(string).TypeHandle`編譯到`ldtoken` CIL指令,但它看起來像CLR會在JIT中處理它。它仍然需要一些額外的操作碼,但它是優化的更廣泛的應用。 – 2010-02-22 18:39:50

+2

閱讀http://higherlogics.blogspot.ca/2013/09/clr-cost-of-dynamic-type-tests.html - 他們重新測試了不同的框架和x86與x64,結果差別很大。 – 2014-07-29 11:21:04

+1

請注意,這僅適用於參考類型。速度差異並不顯着。鑑於`GetType`的值類型的情況下的裝箱懲罰,就性能而言````總是一個更安全的選擇。當然他們做不同的事情。 – nawfal 2014-08-04 07:31:34

23

他們不這樣做。如果obj是ClassA類型或ClassA的某個子類,則第一個工作。第二個只會匹配ClassA類型的對象。第二個將會更快,因爲它不需要檢查類層次結構。

對於那些想知道原因的人,但不想閱讀is vs typeof中引用的文章。

153

如果他們不做同樣的事,哪個更快?比較具有不同含義的語句的表現似乎是一個壞主意。

is告訴你該物體是否在其類型層次中的任何位置實現了ClassAGetType()告訴你最衍生的類型。

不是一回事。

9

我做了一些基準測試,他們也是這樣做的 - 密封類型。

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. 調用GetTypestruct s是慢。GetType定義在object類別中,不能在子類型中覆蓋,因此struct需要裝箱以稱爲GetType

  2. 在對象實例上,GetType速度更快,但非常小。

  3. 在泛型類型,如果Tclass,則is快得多。如果Tstruct,則isGetType快得多,但typeof(T)比兩者快得多。Tclass的情況下,typeof(T)是不可靠的,因爲它與實際的潛在類型t.GetType不同。

總之,如果你有一個object實例,使用GetType。如果您有一個通用的class類型,請使用is。如果您有一個通用的struct類型,請使用typeof(T)。如果您不確定泛型類型是引用類型還是值類型,請使用is。如果你想始終與一種風格保持一致(對於密封類型),請使用is ..