2008-10-08 18 views
118

Bu kod parçalarından hangisi daha hızlıdır?vs typeof

if (obj is ClassA) {} 

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

Düzenleme: Ben aynı şeyi yapmazlar farkındayım.

+1

Benzer bir soruya burada yanıt verin: http://stackoverflow.com/questions/57701/what-are-the-performance-characteristics -of-is-yansıma-in-C# 57713 – swilliams

cevap

142

This should answer that question, and then some.

İkinci satır, if (obj.GetType() == typeof(ClassA)) {}, daha hızlı, makale okumak istemiyorum içindir.

+1

+1: Geçmişte, C# derleyicisinin neden 'ldtoken' CIL komutuna typeof (string) .TypeHandle' derlemediğini merak ettim, ama CLR bunu JIT'de halleder. Yine de birkaç ekstra opcodes gerektiriyor ancak optimizasyonun daha genelleştirilmiş bir uygulaması. –

+2

http://higherlogics.blogspot.ca/2013/09/clr-cost-of-dynamic-type-tests.html adresini de okuyun - farklı çerçeveler ve x86 ile x64 arasında farklı sonuçlar elde etmek için tekrar test ederler. –

+1

Lütfen bunun yalnızca referans türleri için geçerli olduğunu unutmayın. Ve hız farkı bu kadar önemli değil. 'GetType' için değer türleri durumunda boks cezası verildiğinde, performans her zaman için daha güvenli bir seçimdir. Elbette farklı şeyler yaparlar. – nawfal

23

Aynı şeyi yapmıyorlar. İlki, obj ClassA veya ClassA'nın bazı alt sınıfları olduğunda işe yarar. İkincisi sadece ClassA tipi nesneleri eşleştirecektir. İkincisi daha hızlı olacaktır çünkü sınıf hiyerarşisini kontrol etmek zorunda kalmamaktadır. Nedeni bilmek isteyenler için, ancak is vs typeof numaralı başvuruda belirtilen makaleyi okumak istemeyenler için

.

+0

http://stackoverflow.com/q/27813304 “Object is Type” ifadesi daha hızlı olacaktır. –

+1

@amitjha Biraz endişeliyim çünkü bu test, Mono altında çalıştırıldı ve makalede atıfta bulunulan JIT optimizasyonlarını içermiyordu. Makale tersini gösterdiği için aklımda soru açık. Her halükarda, türe bağlı olarak farklı şeyler yapan operasyonların performansının karşılaştırılması, değersiz bir egzersiz gibi görünmektedir. İhtiyacınız olan davranışla eşleşen işlemi kullanın, "daha hızlı" olanı değil. – tvanfosson

153

Aynı şeyi yapmazsa hangisinin daha hızlı olduğu fark eder mi? Farklı anlamdaki ifadelerin performansının karşılaştırılması kötü bir fikir gibi görünüyor. Nesne heirarchy türünde herhangi bir yerde ClassA uygularsa,

. GetType(), en türetilmiş tür hakkında bilgi verir.

Aynı şey değil.

+6

Önemli değil, çünkü benim durumumda da aynı sonucu veriyorlar. – ilitirit

+28

@ [ilitirit]: Şu anda aynı sonucu döndürüyorlar, ancak daha sonra bir alt sınıf eklerseniz, –

+10

kodunuzu artık optimize etmeyeceksiniz. – ICR

9

Aynı mühürlü türleri yaptıkları bazı kıyaslamalar yaptım.

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()); 

jenerik fonksiyonlar jenerik türleri için test etmek:

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

Ben de özel tipleri için denenmiş ve sonuçlar tutarlı idi:

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()); 

Ve türleri:

sealed class Class1 { } 
sealed class Class2 { } 
struct Struct1 { } 
struct Struct2 { } 

Çıkarım: GetTypestruct üzerinde s çağrılması

  1. yavaştır.GetType, alt türlerde geçersiz kılınamayan object sınıfında tanımlanmıştır ve bu nedenle s GetType olarak adlandırılmak üzere kutunun kutulanması gerekir.

  2. Bir nesne örneğinde, GetType daha hızlı ancak çok marjinaldir. Tclass ise genel türü üzerinde

  3. , ardından is daha hızlıdır. Tstruct ise, isGetType'dan çok daha hızlıdır, ancak typeof(T) her ikisinden de daha hızlıdır.Tclass olmak üzere typeof(T), gerçek altta yatan türden farklı olduğu için güvenilir değildir t.GetType.Bir object örneği varsa

Kısacası, GetType kullanın. Genel bir class türüne sahipseniz, is kullanın. Genel bir struct türünüz varsa, typeof(T)'u kullanın. Genel tür referans türü veya değer türü olup olmadığından emin değilseniz, is kullanın. Her zaman (kapalı tipler için) tek bir stille tutarlı olmak istiyorsanız, is kullanın.

+0

Gerçekte, hiç umursama. En mantıklı olanı kullan. – nawfal

İlgili konular