+1: Di masa lalu saya bertanya-tanya mengapa kompiler C # tidak dapat dikompilasi typeof(string).TypeHandledengan ldtokeninstruksi CIL, tetapi sepertinya CLR mengurusnya di JIT. Masih membutuhkan beberapa opcodes tambahan tetapi ini merupakan aplikasi optimisasi yang lebih umum.
Sam Harwell
2
Baca higherlogics.blogspot.ca/2013/09/... - mereka menguji ulang untuk kerangka kerja yang berbeda dan x86 vs x64 dengan hasil yang sangat berbeda.
CAD berbicara
1
Harap dicatat, ini hanya berlaku untuk jenis referensi. Dan perbedaan kecepatan tidak terlalu signifikan. Mengingat penalti tinju dalam hal jenis nilai untuk GetType, isselalu merupakan pilihan yang lebih aman sejauh menyangkut kinerja. Tentu saja mereka melakukan hal yang berbeda.
nawfal
Jika Anda memasukkannya ke dalam Resharper, menyarankan untuk mengubahnya menjadi "adalah"!
Rob Sedgwick
@nawfal, saya awalnya berpikir poin Anda tentang penalti tinju masuk akal untuk jenis struct, tetapi mengingat bahwa kami sedang menguji object obj;variabel, bukankah sudah boxed ketika ini cenderung diuji? Apakah ada kasus di mana Anda perlu menguji jenis sesuatu dan itu belum dikotakkan sebagai objek?
Rob Parker
193
Apakah penting yang lebih cepat, jika mereka tidak melakukan hal yang sama? Membandingkan kinerja pernyataan dengan makna berbeda sepertinya ide yang buruk.
ismemberi tahu Anda jika objek mengimplementasikan ClassAdi mana saja dalam jenis heirarki. GetType()memberi tahu Anda tentang jenis yang paling diturunkan.
Itu penting, karena dalam kasus saya, saya yakin mereka mengembalikan hasil yang sama.
ilitirit
37
@ [ilitirit]: mereka mengembalikan hasil yang sama sekarang, tetapi jika Anda menambahkan subkelas nanti mereka tidak akan
Steven A. Lowe
13
Mengoptimalkan sekarang akan membuat kode Anda rapuh dan sulit dipertahankan.
ICR
9
Kelas saya disegel.
ilitirit
26
Mereka tidak melakukan hal yang sama. Yang pertama berfungsi jika obj adalah tipe ClassA atau beberapa subclass dari ClassA. Yang kedua hanya akan cocok dengan objek bertipe ClassA. Yang kedua akan lebih cepat karena tidak harus memeriksa hierarki kelas.
Bagi mereka yang ingin tahu alasannya, tetapi tidak ingin membaca artikel yang dirujuk adalah vs typeof .
@amitjha Saya sedikit khawatir karena tes itu dijalankan di bawah Mono sehingga tidak termasuk optimasi JIT yang dirujuk dalam artikel. Karena artikel tersebut menunjukkan yang sebaliknya, dalam pikiran saya pertanyaannya adalah pertanyaan terbuka. Dalam hal apa pun, membandingkan kinerja operasi yang melakukan berbagai hal tergantung pada jenisnya tampaknya merupakan latihan yang tidak berharga. Gunakan operasi yang cocok dengan perilaku yang Anda butuhkan, bukan yang "lebih cepat"
tvanfosson
16
Saya melakukan benchmarking di mana mereka melakukan jenis yang sama - disegel.
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 isstring;// ~60ms
b = c2.GetType()==typeof(string);// ~60ms
b = c2 isstring;// ~50ms
b = oc1.GetType()==typeof(string);// ~60ms
b = oc1 isstring;// ~68ms
b = oc2.GetType()==typeof(string);// ~60ms
b = oc2 isstring;// ~64ms
b = s1.GetType()==typeof(int);// ~130ms
b = s1 isint;// ~50ms
b = s2.GetType()==typeof(int);// ~140ms
b = s2 isint;// ~50ms
b = os1.GetType()==typeof(int);// ~60ms
b = os1 isint;// ~74ms
b = os2.GetType()==typeof(int);// ~60ms
b = os2 isint;// ~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());
Fungsi generik untuk menguji tipe generik:
staticboolGetType1<S, T>(T t){return t.GetType()==typeof(S);}staticboolGetType2<S, T>(T t){returntypeof(T)==typeof(S);}staticboolIs<S, T>(T t){return t is S;}
Saya mencoba jenis kustom juga dan hasilnya konsisten:
var c1 =newClass1();var c2 =newClass2();object oc1 = c1;object oc2 = c2;var s1 =newStruct1();var s2 =newStruct2();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 isClass1;// ~60ms
b = c2.GetType()==typeof(Class1);// ~60ms
b = c2 isClass1;// ~55ms
b = oc1.GetType()==typeof(Class1);// ~60ms
b = oc1 isClass1;// ~68ms
b = oc2.GetType()==typeof(Class1);// ~60ms
b = oc2 isClass1;// ~68ms
b = s1.GetType()==typeof(Struct1);// ~150ms
b = s1 isStruct1;// ~50ms
b = s2.GetType()==typeof(Struct1);// ~150ms
b = s2 isStruct1;// ~50ms
b = os1.GetType()==typeof(Struct1);// ~60ms
b = os1 isStruct1;// ~64ms
b = os2.GetType()==typeof(Struct1);// ~60ms
b = os2 isStruct1;// ~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());
Memanggil GetTypedi structs lebih lambat. GetTypedidefinisikan pada objectkelas yang tidak dapat diganti dalam sub tipe dan dengan demikian structperlu dikotak untuk dipanggil GetType.
Pada instance objek, GetTypelebih cepat, tetapi sangat marginal.
Pada jenis generik, jika Tyaitu class, maka isjauh lebih cepat. Jika Tini struct, maka isjauh lebih cepat daripada GetTypetetapi typeof(T)jauh lebih cepat dari keduanya. Dalam kasus Tsedang class, typeof(T)tidak dapat diandalkan karena berbeda dari tipe yang mendasarinya sebenarnya t.GetType.
Singkatnya, jika Anda memiliki sebuah objectinstance, gunakan GetType. Jika Anda memiliki classtipe generik , gunakan is. Jika Anda memiliki structtipe generik , gunakan typeof(T). Jika Anda tidak yakin apakah tipe generik adalah tipe referensi atau tipe nilai, gunakan is. Jika Anda ingin konsisten dengan satu gaya selalu (untuk tipe tertutup), gunakan is..
Jawaban:
Ini harus menjawab pertanyaan itu, dan kemudian beberapa.
Baris kedua,,
if (obj.GetType() == typeof(ClassA)) {}
lebih cepat, bagi mereka yang tidak ingin membaca artikel.(Ketahuilah bahwa mereka tidak melakukan hal yang sama)
sumber
typeof(string).TypeHandle
denganldtoken
instruksi CIL, tetapi sepertinya CLR mengurusnya di JIT. Masih membutuhkan beberapa opcodes tambahan tetapi ini merupakan aplikasi optimisasi yang lebih umum.GetType
,is
selalu merupakan pilihan yang lebih aman sejauh menyangkut kinerja. Tentu saja mereka melakukan hal yang berbeda.object obj;
variabel, bukankah sudah boxed ketika ini cenderung diuji? Apakah ada kasus di mana Anda perlu menguji jenis sesuatu dan itu belum dikotakkan sebagai objek?Apakah penting yang lebih cepat, jika mereka tidak melakukan hal yang sama? Membandingkan kinerja pernyataan dengan makna berbeda sepertinya ide yang buruk.
is
memberi tahu Anda jika objek mengimplementasikanClassA
di mana saja dalam jenis heirarki.GetType()
memberi tahu Anda tentang jenis yang paling diturunkan.Bukan hal yang sama.
sumber
Mereka tidak melakukan hal yang sama. Yang pertama berfungsi jika obj adalah tipe ClassA atau beberapa subclass dari ClassA. Yang kedua hanya akan cocok dengan objek bertipe ClassA. Yang kedua akan lebih cepat karena tidak harus memeriksa hierarki kelas.
Bagi mereka yang ingin tahu alasannya, tetapi tidak ingin membaca artikel yang dirujuk adalah vs typeof .
sumber
Saya melakukan benchmarking di mana mereka melakukan jenis yang sama - disegel.
Fungsi generik untuk menguji tipe generik:
Saya mencoba jenis kustom juga dan hasilnya konsisten:
Dan jenisnya:
Kesimpulan:
Memanggil
GetType
distruct
s lebih lambat.GetType
didefinisikan padaobject
kelas yang tidak dapat diganti dalam sub tipe dan dengan demikianstruct
perlu dikotak untuk dipanggilGetType
.Pada instance objek,
GetType
lebih cepat, tetapi sangat marginal.Pada jenis generik, jika
T
yaituclass
, makais
jauh lebih cepat. JikaT
inistruct
, makais
jauh lebih cepat daripadaGetType
tetapitypeof(T)
jauh lebih cepat dari keduanya. Dalam kasusT
sedangclass
,typeof(T)
tidak dapat diandalkan karena berbeda dari tipe yang mendasarinya sebenarnyat.GetType
.Singkatnya, jika Anda memiliki sebuah
object
instance, gunakanGetType
. Jika Anda memilikiclass
tipe generik , gunakanis
. Jika Anda memilikistruct
tipe generik , gunakantypeof(T)
. Jika Anda tidak yakin apakah tipe generik adalah tipe referensi atau tipe nilai, gunakanis
. Jika Anda ingin konsisten dengan satu gaya selalu (untuk tipe tertutup), gunakanis
..sumber