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 o
adalah Dog
, bukan Animal
. Anda dapat membuat ini berfungsi, jika Anda menggunakan IsAssignableFrom
metode Type
kelas.
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 is
kata kunci yang setara . Karenanya, jika ini adalah perilaku yang Anda inginkan, Anda harus menggunakan is
kata kunci, yang lebih mudah dibaca dan lebih efisien.
if(o is Animal)
Console.WriteLine("o is an animal");
Namun, dalam kebanyakan kasus, is
kata 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 is
operator, dan jika o
memang 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 as
operator 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 o
akan 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 InvalidCastException
gantinya, 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 o
menjadi Animal
setiap waktu, tetapi ini tidak jelas dalam konstruktor, di mana para as
pemain digunakan. Tidak jelas sampai Anda mencapai Interact
metode, di mana animal
bidang 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 as
dan periksa null
.
Jika Anda perlu memperlakukan objek sebagai turunan dari jenis tertentu, dan objek tersebut seharusnya dari jenis itu, gunakan gips biasa.
as
!