Bagaimana memeriksa apakah jenis variabel cocok dengan Jenis yang disimpan dalam variabel

96
User u = new User();
Type t = typeof(User);

u is User -> returns true

u is t -> compilation error

Bagaimana cara menguji jika beberapa variabel memiliki beberapa tipe dengan cara ini?

Karan
sumber

Jawaban:

194

Jawaban lainnya semuanya mengandung kelalaian yang signifikan.

The isOperator tidak tidak memeriksa apakah jenis runtime dari operan adalah persis jenis yang diberikan; sebaliknya, ia memeriksa apakah tipe runtime kompatibel dengan tipe yang diberikan:

class Animal {}
class Tiger : Animal {}
...
object x = new Tiger();
bool b1 = x is Tiger; // true
bool b2 = x is Animal; // true also! Every tiger is an animal.

Tetapi memeriksa identitas tipe dengan refleksi memeriksa identitas , bukan untuk kompatibilitas

bool b5 = x.GetType() == typeof(Tiger); // true
bool b6 = x.GetType() == typeof(Animal); // false! even though x is an animal

or with the type variable
bool b7 = t == typeof(Tiger); // true
bool b8 = t == typeof(Animal); // false! even though x is an 

Jika bukan itu yang Anda inginkan, Anda mungkin menginginkan IsAssignableFrom:

bool b9 = typeof(Tiger).IsAssignableFrom(x.GetType()); // true
bool b10 = typeof(Animal).IsAssignableFrom(x.GetType()); // true! A variable of type Animal may be assigned a Tiger.

or with the type variable
bool b11 = t.IsAssignableFrom(x.GetType()); // true
bool b12 = t.IsAssignableFrom(x.GetType()); // true! A 
Eric Lippert
sumber
4
Sementara pendekatan terakhir yang ditunjukkan di sini berfungsi, itu tidak perlu bertele-tele. typeof(Animal).IsInstanceOfType(x)lebih pendek dan lebih mudah daripada typeof(Animal).IsAssignableFrom(x.GetType());(dan Resharper akan menyarankan menggunakan yang pertama jika Anda menggunakan yang terakhir).
Mark Amery
KLARIFIKASI: untuk menjawab pertanyaan awal, pengganti tuntuk typeof(Animal). Jadi bentuk Mark yang ditingkatkan menjadi t.IsInstanceOfType(x).
ToolmakerSteve
13

GetType()ada di setiap jenis kerangka kerja, karena ditentukan pada objectjenis dasar . Jadi, apa pun tipenya, Anda dapat menggunakannya untuk mengembalikan yang mendasarinyaType

Jadi, yang perlu Anda lakukan hanyalah:

u.GetType() == t
Dave Bish
sumber
1
Sebenarnya jawaban Eric sangat membantu dan semuanya, tetapi tidak menjawab pertanyaan sebenarnya tentang bagaimana menguji dengan tipe yang tidak diketahui dengan cara "u is t" yang dijelaskan dalam pertanyaan asli, dan milik Anda melakukannya.
Daniel
@ Daniel - Tidak juga. Jawaban Dave hanya benar jika Anda ingin mengecualikan subclass dari t. Jawaban Eric kebanyakan menjelaskan apa yang harus dilakukan; itu hanya klarifikasi yang hilang tentang di mana harus meletakkan "t". Saya akan menambahkan komentar di sana.
ToolmakerSteve
10

Anda perlu melihat apakah Jenis instans Anda sama dengan Jenis kelas. Untuk mendapatkan jenis instance, Anda menggunakan GetType()metode:

 u.GetType().Equals(t);

atau

 u.GetType.Equals(typeof(User));

harus melakukannya. Jelas Anda bisa menggunakan '==' untuk melakukan perbandingan jika Anda mau.

Sam Holder
sumber
+1 Tapi lebih suka pilihan kedua. u.GetType.Equals(typeof(User));
Omar
Salah satu alasan mengapa ini kurang aman daripada menggunakan == - adalah jika GetType () entah bagaimana mengembalikan null - itu akan melempar.
Dave Bish
1
@Fuex, ya saya juga, menurut saya itu membuat kode lebih mudah dibaca jika jenisnya inline, itulah sebabnya saya mempostingnya seperti itu, padahal di contoh OP dia sudah memiliki variabel tyang berisi tipe.
Sam Holder
@DaveBish jika GetType mengembalikan null, maka saya khawatir banyak hal akan mulai terlempar ... tetapi poin yang diambil, Anda tentu saja benar
Sam Holder
@ SamHolder Ya - Satu-satunya situasi ini akan terjadi, jika seseorang mengesampingkan tipe dasar, dan mengacaukan implementasinya entah bagaimana. Ini pasti aneh.
Dave Bish
4

Untuk memeriksa apakah suatu objek kompatibel dengan variabel tipe tertentu, daripada menulis

u is t

kamu harus menulis

typeof(t).IsInstanceOfType(u)
Mantas Janulionis
sumber
1
Apa keuntungan dari sintaks yang lebih verbose versus sintaks 'u is t'?
Kyle Humfeld
@TikTeam Objek A; Anda tidak dapat menulis "A is foo", tetapi Anda dapat menulis foo.isInstanceOfType (A)
Timur Nuriyasov