Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Ini adalah kesalahan. Operator typeof di C # hanya bisa mengambil nama tipe, bukan objek.
if (obj1.GetType() == typeof(int))
// Some code here
Ini akan berhasil, tetapi mungkin tidak seperti yang Anda harapkan. Untuk tipe nilai, seperti yang Anda tunjukkan di sini, itu dapat diterima, tetapi untuk tipe referensi, itu hanya akan mengembalikan true jika jenisnya adalah tipe yang sama persis , bukan sesuatu yang lain dalam hierarki warisan. 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 jenisnya oadalah Dog, bukan Animal. Anda dapat membuat ini berfungsi, jika Anda menggunakan IsAssignableFrommetode Typekelas.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Teknik ini masih menyisakan masalah besar. Jika variabel Anda nol, panggilan ke GetType()akan melempar NullReferenceException. Jadi untuk membuatnya bekerja dengan benar, Anda harus:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Dengan ini, Anda memiliki perilaku iskata kunci yang setara . Karenanya, jika ini adalah perilaku yang Anda inginkan, Anda harus menggunakan iskata kunci, yang lebih mudah dibaca dan lebih efisien.
if(o is Animal)
Console.WriteLine("o is an animal");
Namun, dalam kebanyakan kasus, iskata kunci masih bukan yang Anda inginkan, karena biasanya tidak cukup hanya untuk mengetahui bahwa suatu objek adalah tipe tertentu. Biasanya, Anda ingin benar-benar menggunakan objek itu sebagai turunan dari tipe itu, yang memerlukan casting juga. Jadi Anda mungkin menemukan diri Anda menulis kode seperti ini:
if(o is Animal)
((Animal)o).Speak();
Tapi itu membuat CLR memeriksa jenis objek hingga dua kali. Ini akan memeriksa sekali untuk memuaskan isoperator, dan jika omemang benar Animal, kami membuatnya memeriksa lagi untuk memvalidasi para pemain.
Lebih efisien untuk melakukan ini sebagai gantinya:
Animal a = o as Animal;
if(a != null)
a.Speak();
The asoperator adalah pemain yang tidak akan melemparkan sebuah pengecualian jika gagal, bukan kembali null. Dengan cara ini, CLR memeriksa jenis objek hanya sekali, dan setelah itu, kita hanya perlu melakukan pemeriksaan nol, yang lebih efisien.
Tetapi waspadalah: banyak orang jatuh ke dalam perangkap as. Karena tidak membuang pengecualian, beberapa orang menganggapnya sebagai gips "aman", dan mereka menggunakannya secara eksklusif, menghindari gips biasa. Ini mengarah ke kesalahan seperti ini:
(o as Animal).Speak();
Dalam hal ini, pengembang dengan jelas mengasumsikan bahwa oakan selalu menjadi Animal, dan selama asumsinya benar, semuanya berfungsi dengan baik. Tetapi jika mereka salah, maka apa yang akhirnya mereka dapatkan di sini adalah a NullReferenceException. Dengan pemain reguler, mereka akan mendapatkan InvalidCastExceptiongantinya, yang akan lebih tepat mengidentifikasi masalah.
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 jelas berharap omenjadi Animalsetiap waktu, tetapi ini tidak jelas dalam konstruktor, di mana para aspemain digunakan. Tidak jelas sampai Anda mencapai Interactmetode, di mana animalbidang diharapkan ditugaskan secara positif. Dalam hal ini, Anda tidak hanya berakhir dengan pengecualian yang menyesatkan, tetapi tidak dibuang hingga berpotensi lebih lama daripada saat kesalahan sebenarnya terjadi.
Singkatnya:
Jika Anda hanya perlu tahu apakah suatu objek memiliki tipe tertentu atau tidak, gunakan is.
Jika Anda perlu memperlakukan objek sebagai instance dari tipe tertentu, tetapi Anda tidak tahu pasti bahwa objek tersebut akan dari tipe itu, gunakan asdan periksa null.
Jika Anda perlu memperlakukan objek sebagai turunan dari jenis tertentu, dan objek tersebut seharusnya dari jenis itu, gunakan gips biasa.
as!