Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Ini adalah sebuah kesalahan. Operator typeof di C# hanya dapat mengambil nama tipe, bukan objek.
if (obj1.GetType() == typeof(int))
// Some code here
Ini akan berhasil, tapi mungkin tidak seperti yang Anda harapkan. Untuk tipe nilai, seperti yang Anda tunjukkan di sini, nilai tersebut dapat diterima, namun untuk tipe referensi, nilai tersebut hanya akan menghasilkan nilai true jika tipe tersebut adalah tipe yang sama persis, bukan tipe lain dalam hierarki pewarisan. Contohnya:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
Ini akan mencetak "o is something else"
, karena tipe o
adalah Dog
, bukan Animal
. Namun Anda dapat membuat ini berfungsi jika Anda menggunakan metode IsAssignableFrom
dari kelas Type
.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Namun teknik ini masih menyisakan masalah besar. Jika variabel Anda null, panggilan ke GetType()
akan memunculkan NullReferenceException. Jadi untuk membuatnya berfungsi dengan benar, Anda harus melakukan:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Dengan ini, Anda memiliki perilaku yang setara dengan kata kunci is
. Oleh karena itu, jika ini adalah perilaku yang Anda inginkan, Anda harus menggunakan kata kunci is
, yang lebih mudah dibaca dan efisien.
if(o is Animal)
Console.WriteLine("o is an animal");
Namun dalam kebanyakan kasus, kata kunci is
masih belum sesuai dengan keinginan Anda, karena biasanya tidak cukup hanya dengan mengetahui bahwa suatu objek bertipe tertentu. Biasanya, Anda ingin menggunakan objek tersebut sebagai turunan dari tipe tersebut, sehingga memerlukan casting juga. Jadi Anda mungkin mendapati diri Anda menulis kode seperti ini:
if(o is Animal)
((Animal)o).Speak();
Namun hal itu membuat CLR memeriksa tipe objek hingga dua kali. Ia akan memeriksanya sekali untuk memenuhi operator is
, dan jika o
memang Animal
, kami memeriksanya lagi untuk memvalidasi pemerannya.
Lebih efisien melakukan ini:
Animal a = o as Animal;
if(a != null)
a.Speak();
Operator as
adalah pemeran yang tidak akan mengeluarkan pengecualian jika gagal, melainkan mengembalikan null
. Dengan cara ini, CLR memeriksa tipe objek sekali saja, dan setelah itu, kita hanya perlu melakukan pemeriksaan null, yang mana lebih efisien.
Namun hati-hati: banyak orang terjebak dengan as
. Karena tidak memberikan pengecualian, beberapa orang menganggapnya sebagai gips yang "aman", dan mereka menggunakannya secara eksklusif, menghindari gips biasa. Hal ini menyebabkan kesalahan seperti ini:
(o as Animal).Speak();
Dalam hal ini, pengembang dengan jelas berasumsi bahwa o
akan selalu menjadi Animal
, dan selama asumsi mereka benar, semuanya berfungsi dengan baik. Namun jika mereka salah, maka yang mereka dapatkan di sini adalah NullReferenceException
. Dengan pemeran reguler, mereka akan mendapatkan InvalidCastException
, yang akan mengidentifikasi masalahnya dengan lebih tepat.
Terkadang, bug ini sulit ditemukan:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
Ini adalah kasus lain di mana pengembang dengan jelas mengharapkan o
menjadi Animal
setiap saat, namun hal ini tidak terlihat jelas di konstruktor, tempat pemeran as
digunakan. Ini tidak jelas sampai Anda mendapatkan metode Interact
, di mana bidang animal
diharapkan ditetapkan secara positif. Dalam kasus ini, Anda tidak hanya akan mendapatkan pengecualian yang menyesatkan, namun pengecualian tersebut juga tidak akan muncul hingga kemungkinan terjadi lebih lama dibandingkan saat kesalahan sebenarnya terjadi.
Kesimpulan:
Jika Anda hanya perlu mengetahui apakah suatu objek bertipe tertentu atau tidak, gunakan is
.
Jika Anda perlu memperlakukan suatu objek sebagai turunan dari tipe tertentu, tetapi Anda tidak tahu pasti apakah objek tersebut akan bertipe tersebut, gunakan as
dan periksa null
.
Jika Anda perlu memperlakukan suatu objek sebagai turunan dari tipe tertentu, dan objek tersebut seharusnya bertipe tersebut, gunakan cast biasa.
person
P Daddy
schedule
11.06.2009
as
! - person RCIX   schedule 08.10.2009as
tidak benar-benar memeriksa tipe... - person jasonh   schedule 08.10.2009as
tentu saja merupakan bentuk pengecekan tipe, sama sepertiis
! Ini secara efektif menggunakanis
di belakang layar, dan digunakan di semua tempat di MSDN di mana ia meningkatkan kebersihan kode dibandingkanis
. Daripada memeriksais
terlebih dahulu, panggilan keas
membuat variabel yang diketik siap digunakan: Jika nilainya nol, tanggapi dengan tepat; jika tidak, lanjutkan. Tentu saja sesuatu yang sering saya lihat dan gunakan. - person Zaccone   schedule 20.08.2014as
/is
(dibahas dalam stackoverflow.com/a/27813381/477420) dengan asumsi semantik berfungsi untuk kasus Anda. - person Alexei Levenkov   schedule 07.01.2015GetType
yang Anda tautkan ada diSystem.Reflection.Assembly
-- metode yang sama sekali berbeda dan tidak relevan di sini. - person Kirk Woll   schedule 11.08.2017