vs typeof


Yanıtlar:


167

Bu, bu soruya ve sonra bazılarına cevap vermelidir.

İkinci satır,, if (obj.GetType() == typeof(ClassA)) {}makaleyi okumak istemeyenler için daha hızlıdır.

(Aynı şeyi yapmadıklarını unutmayın)


1
1: Geçmişte C # derleyicisi derleme vermedi merak ettim typeof(string).TypeHandleetmek ldtokenCIL talimat, ancak CLR JIT içinde bunu halleder gibi görünüyor. Yine de birkaç ekstra opcodes gerekiyor, ancak optimizasyonun daha genel bir uygulaması.
Sam Harwell

2
Higherlogics.blogspot.ca/2013/09/… 'ı da okuyun - farklı çerçeveler ve x86 ve x64 için tekrar test ederler ve çok farklı sonuçlar alırlar.
CAD bloke

1
Bunun yalnızca referans türleri için geçerli olduğunu lütfen unutmayın. Ve hız farkı o kadar da önemli değil. İçin değer türleri durumunda boks penaltı önüne alındığında GetType, isperformansı söz konusu olduğunda kadarıyla olarak daha güvenli bir seçim her zaman olduğunu. Elbette farklı şeyler yapıyorlar.
nawfal

Eğer Resharper koyarsanız bunu "is" olarak değiştirmenizi önerir!
Rob Sedgwick

@nawfal, başlangıçta yapı türleri için boks cezası hakkında ne düşündüğünüzü düşündüm, ancak bir object obj;değişkeni test ettiğimiz göz önüne alındığında, bu test etme eğiliminde olduğunda zaten kutulu değil mi? Bir şeyin türünü test etmeniz gereken bir durum var mı ve zaten bir nesne olarak kutulu değil mi?
Rob Parker

193

Aynı şeyi yapmazlarsa hangisinin daha hızlı olduğu önemli mi? İfadelerin performanslarını farklı anlamlarla karşılaştırmak kötü bir fikir gibi görünüyor.

isnesnenin ClassAkendi heirarchy türünde herhangi bir yerde uygulanıp uygulanmadığını söyler . GetType()size en türetilmiş türü anlatır.

Aynı şey değil.


7
Önemli, çünkü benim durumumda aynı sonucu döndürdükleri için pozitifim.
ilitirit

37
@ [ilitirit]: şu anda aynı sonucu veriyorlar, ancak daha sonra bir alt sınıf eklerseniz, olmayacaklar
Steven A. Lowe

13
Şimdi optimizasyon yapmak kodunuzu kırılgan ve bakımını zorlaştıracaktır.
ICR

9
Derslerim mühürlendi.
ilitirit

26

Aynı şeyi yapmıyorlar. İlki, ClassA türünde veya ClassA'nın bazı alt sınıflarındaysa çalışır. İkincisi sadece ClassA türündeki nesnelerle eşleşir. İkincisi, sınıf hiyerarşisini kontrol etmek zorunda olmadığından daha hızlı olacaktır.

Nedeni bilmek isteyenler için, ancak atıfta bulunulan makaleyi okumak istemeyenler için vs typeof .


1
@amitjha Bu test Mono altında çalıştırıldığı için makalede referans verilen JIT optimizasyonlarını içermediğinden endişeliyim. Makale tam tersini gösterdiğinden, bence soru açık bir sorudur. Her durumda, türe bağlı olarak farklı şeyler yapan işlemlerin performansının karşılaştırılması değersiz bir egzersiz gibi görünüyor. "Daha hızlı"
olana

16

Aynı mühürlü türleri yaptıkları yerde 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());

Genel türleri test etmek için genel fonksiyonlar:

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

Özel türler için de denedim ve sonuçlar tutarlıydı:

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:

  1. Arama GetTypeüzerinde structs yavaştır. alt tiplerde geçersiz kılınamayan sınıfta GetTypetanımlanır objectve bu nedenle structçağrılması için kutulu olması gerekir GetType.

  2. Bir nesne örneğinde, GetTypedaha hızlı, ama çok marjinal.

  3. Genel türü günü, eğer TIS class, o zaman isçok daha hızlıdır. Eğer Tbir struct, daha sonra isçok daha hızlı daha GetTypeama typeof(T)çok daha hızlı hem daha olduğunu. Durumlarında Tvarlık class, typeof(T)gerçek temel türünden Farklı beri güvenilir değildir t.GetType.

Kısacası, bir objectörneğiniz varsa kullanın GetType. Genel bir classtürünüz varsa kullanın is. Genel bir structtürünüz varsa kullanın typeof(T). Genel türün başvuru türü veya değer türü olduğundan emin değilseniz kullanın is. Her zaman bir stil ile tutarlı olmak istiyorsanız (mühürlü tipler için), kullanın is..


1
Gerçekte, hiç umrumda değil. En mantıklı olanı kullanın.
nawfal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.