Saya telah melihat banyak orang menggunakan kode berikut:
Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Tapi saya tahu Anda juga bisa melakukan ini:
if (obj1.GetType() == typeof(int))
// Some code here
Atau ini:
if (obj1 is int)
// Some code here
Secara pribadi, saya merasa yang terakhir adalah yang terbersih, tetapi apakah ada sesuatu yang saya lewatkan? Mana yang terbaik untuk digunakan, atau preferensi pribadi?
as
!as
tidak benar-benar memeriksa jenis meskipun ...as
tentu saja merupakan bentuk pengecekan tipe, setiap bit sebanyakis
itu! Ini secara efektif menggunakan diis
belakang layar, dan digunakan di semua tempat di MSDN di tempat-tempat di mana ia meningkatkan kebersihan kode versusis
. Alih-alih memeriksais
terlebih dahulu, panggilan untukas
membuat variabel yang diketik siap digunakan: Jika nol, jawab dengan tepat; jika tidak, lanjutkan. Tentu saja sesuatu yang saya lihat dan gunakan sedikit.as
/is
(tercakup dalam stackoverflow.com/a/27813381/477420 ) dengan asumsi semantiknya berfungsi untuk kasing Anda.GetType
Metode Anda terhubung ke dalamSystem.Reflection.Assembly
- metode yang sama sekali berbeda dan tidak relevan di sini.Jawaban:
Semua berbeda.
typeof
membutuhkan nama tipe (yang Anda tentukan pada waktu kompilasi).GetType
mendapatkan tipe runtime dari sebuah instance.is
mengembalikan true jika turunan ada di pohon warisan.Contoh
Iya. T selalu seperti apa jenis ekspresinya. Ingat, metode generik pada dasarnya adalah sejumlah metode dengan tipe yang sesuai. Contoh:
sumber
new Dog().GetType() is Animal
mengembalikan false (dan versi Anda yang lain juga) karena.GetType()
mengembalikan objek bertipeType
, danType
bukanAnimal
.Gunakan
typeof
saat Anda ingin mendapatkan jenis pada waktu kompilasi . GunakanGetType
saat Anda ingin mendapatkan jenis pada waktu eksekusi . Jarang ada kasus untuk digunakanis
karena melakukan pemeran dan, dalam kebanyakan kasus, Anda akhirnya casting variabel.Ada opsi keempat yang belum Anda pertimbangkan (terutama jika Anda akan melemparkan objek ke jenis yang Anda temukan juga); itu untuk digunakan
as
.Ini hanya menggunakan satu pemeran
sedangkan pendekatan ini:membutuhkan dua .Pembaruan (Jan 2020):
Contoh:
sumber
is
masih melakukan gips?typeof()
, dan jawaban ini tidak menyarankan Anda bisa. Anda memasukkan jenis sebagai gantinya, yaitu,typeof(string)
bekerja,typeof("foo")
tidak.is
melakukan pemeran, operasi yang agak khusus di IL.if (obj is Foo foo) { /* use foo here */ }
1.
Ini ilegal, karena
typeof
hanya berfungsi pada tipe, bukan pada variabel. Saya menganggap obj1 adalah variabel. Jadi, dengan caratypeof
ini statis, dan tidak berfungsi pada waktu kompilasi alih-alih runtime.2.
Ini
true
jikaobj1
persis tipeint
. Jikaobj1
berasal dariint
, kondisi if akanfalse
.3.
Ini adalah
true
jikaobj1
adalahint
, atau jika berasal dari kelas yang disebutint
, atau jika mengimplementasikan antarmuka yang disebutint
.sumber
Ini adalah kesalahan. Operator typeof di C # hanya bisa mengambil nama tipe, bukan objek.
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:
Ini akan mencetak
"o is something else"
, karena jenisnyao
adalahDog
, bukanAnimal
. Anda dapat membuat ini berfungsi, jika Anda menggunakanIsAssignableFrom
metodeType
kelas.Teknik ini masih menyisakan masalah besar. Jika variabel Anda nol, panggilan ke
GetType()
akan melempar NullReferenceException. Jadi untuk membuatnya bekerja dengan benar, Anda harus:Dengan ini, Anda memiliki perilaku
is
kata kunci yang setara . Karenanya, jika ini adalah perilaku yang Anda inginkan, Anda harus menggunakanis
kata kunci, yang lebih mudah dibaca dan lebih efisien.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:Tapi itu membuat CLR memeriksa jenis objek hingga dua kali. Ini akan memeriksa sekali untuk memuaskan
is
operator, dan jikao
memang benarAnimal
, kami membuatnya memeriksa lagi untuk memvalidasi para pemain.Lebih efisien untuk melakukan ini sebagai gantinya:
The
as
operator adalah pemain yang tidak akan melemparkan sebuah pengecualian jika gagal, bukan kembalinull
. 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:Dalam hal ini, pengembang dengan jelas mengasumsikan bahwa
o
akan selalu menjadiAnimal
, dan selama asumsinya benar, semuanya berfungsi dengan baik. Tetapi jika mereka salah, maka apa yang akhirnya mereka dapatkan di sini adalah aNullReferenceException
. Dengan pemain reguler, mereka akan mendapatkanInvalidCastException
gantinya, yang akan lebih tepat mengidentifikasi masalah.Terkadang, bug ini sulit ditemukan:
Ini adalah kasus lain di mana pengembang jelas berharap
o
menjadiAnimal
setiap waktu, tetapi ini tidak jelas dalam konstruktor, di mana paraas
pemain digunakan. Tidak jelas sampai Anda mencapaiInteract
metode, di manaanimal
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 periksanull
.Jika Anda perlu memperlakukan objek sebagai turunan dari jenis tertentu, dan objek tersebut seharusnya dari jenis itu, gunakan gips biasa.
sumber
o is Animal
, yang mengharuskan CLR untuk memeriksa apakah jenis variabelnyao
adalahAnimal
. Kali kedua ia mengecek adalah ketika dilemparkan dalam pernyataan((Animal)o).Speak()
. Daripada memeriksa dua kali, periksa sekali menggunakanas
.Jika Anda menggunakan C # 7, maka sudah saatnya pembaruan untuk jawaban hebat Andrew Hare. Pencocokan pola telah memperkenalkan jalan pintas yang bagus yang memberi kita variabel yang diketik dalam konteks pernyataan if, tanpa memerlukan deklarasi / pemeran yang terpisah dan periksa:
Ini terlihat sangat underwhelming untuk pemain tunggal seperti ini, tetapi benar-benar bersinar ketika Anda memiliki banyak jenis yang mungkin masuk ke rutinitas Anda. Di bawah ini adalah cara lama untuk menghindari casting dua kali:
Bekerja di sekitar menyusutkan kode ini sebanyak mungkin, serta menghindari gips duplikat dari objek yang sama selalu mengganggu saya. Di atas dikompresi dengan baik dengan pencocokan pola sebagai berikut:
EDIT: Memperbarui metode baru yang lebih lama untuk menggunakan sakelar sesuai komentar Palec.
sumber
switch
pernyataan dengan pola yang cocok .if (obj1 is int integerValue) { integerValue++; }
Saya memiliki
Type
-properti untuk dibandingkan dan tidak dapat menggunakanis
(sepertimy_type is _BaseTypetoLookFor
), tapi saya bisa menggunakan ini:Perhatikan itu
IsInstanceOfType
danIsAssignableFrom
kembalitrue
ketika membandingkan jenis yang sama, di mana IsSubClassOf akan kembalifalse
. DanIsSubclassOf
tidak bekerja pada antarmuka, di mana dua lainnya. (Lihat juga pertanyaan dan jawaban ini .)sumber
Saya lebih suka itu
Yang mengatakan, jika Anda menggunakan itu , Anda kemungkinan tidak menggunakan warisan dengan benar.
Asumsikan Orang itu: Entitas, dan Hewan itu: Entitas. Umpan adalah metode virtual di Entity (untuk membuat Neil senang)
Agak
sumber
Saya percaya yang terakhir juga melihat pewarisan (misalnya Dog is Animal == true), yang lebih baik dalam kebanyakan kasus.
sumber
Tergantung pada apa yang saya lakukan. Jika saya membutuhkan nilai bool (katakanlah, untuk menentukan apakah saya akan menggunakan int), saya akan menggunakan
is
. Jika saya benar-benar membutuhkan jenis untuk beberapa alasan (katakanlah, untuk meneruskan ke metode lain) saya akan menggunakanGetType()
.sumber
Yang terakhir lebih bersih, lebih jelas, dan juga memeriksa subtipe. Yang lain tidak memeriksa polimorfisme.
sumber
Digunakan untuk mendapatkan objek System.Type untuk suatu jenis. Jenis ekspresi mengambil bentuk berikut:
Sampel ini menggunakan metode GetType untuk menentukan tipe yang digunakan untuk memuat hasil perhitungan numerik. Ini tergantung pada persyaratan penyimpanan nomor yang dihasilkan.
sumber
sumber
Anda dapat menggunakan operator "typeof ()" di C # tetapi Anda harus memanggil namespace menggunakan System.IO; Anda harus menggunakan kata kunci "is" jika Anda ingin memeriksa suatu jenis.
sumber
typeof
tidak didefinisikan dalam namespace, itu adalah kata kunci.System.IO
tidak ada hubungannya dengan ini.Jenis tes kinerja () vs GetType ():
Hasil dalam mode debug:
Hasil dalam mode rilis:
sumber
DateTime
tidak boleh digunakan jika Anda khawatir tentang waktu di bawah 100ms , karena menggunakan jangka waktu OS. Dibandingkan denganStopwatch
, yang menggunakan prosesorTick
, resolusi yang digunakan olehDateTime
dalam Win7 adalah 15ms rejan.