วิธีตรวจสอบว่าประเภทของตัวแปรตรงกับประเภทที่เก็บไว้ในตัวแปรหรือไม่


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

u is User -> returns true

u is t -> compilation error

ฉันจะทดสอบได้อย่างไรว่าตัวแปรบางตัวเป็นบางประเภทด้วยวิธีนี้

คำตอบ:


197

คำตอบอื่น ๆ ทั้งหมดมีการละเว้นอย่างมีนัยสำคัญ

ตัวisดำเนินการไม่ได้ตรวจสอบว่าประเภทรันไทม์ของตัวถูกดำเนินการตรงกับประเภทที่กำหนดหรือไม่ แต่จะตรวจสอบเพื่อดูว่าประเภทรันไทม์เข้ากันได้กับประเภทที่กำหนดหรือไม่:

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.

แต่การตรวจสอบเอกลักษณ์ประเภทด้วยการสะท้อนตรวจสอบเอกลักษณ์ไม่ใช่เพื่อความเข้ากันได้

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 

หากนั่นไม่ใช่สิ่งที่คุณต้องการคุณอาจต้องการ 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 

4
ในขณะที่แนวทางสุดท้ายที่แสดงที่นี่ใช้ได้ผล แต่ก็ไม่จำเป็นต้องละเอียด typeof(Animal).IsInstanceOfType(x)สั้นกว่าและตรงไปตรงมากว่าtypeof(Animal).IsAssignableFrom(x.GetType());(และ Resharper จะแนะนำให้ใช้แบบเดิมถ้าคุณใช้แบบหลัง)
Mark Amery

ชี้แจง: ที่จะตอบคำถามเดิมแทนสำหรับt ดังนั้นรูปแบบที่ดีขึ้นมาร์กจะกลายเป็นtypeof(Animal) t.IsInstanceOfType(x)
ToolmakerSteve

13

GetType()มีอยู่ในทุกประเภทเฟรมเวิร์กเดียวเนื่องจากถูกกำหนดบนobjectประเภทฐาน ดังนั้นไม่ว่าจะเป็นประเภทใดก็ตามคุณสามารถใช้มันเพื่อส่งคืนพื้นฐานได้Type

ดังนั้นสิ่งที่คุณต้องทำคือ:

u.GetType() == t

1
จริงๆแล้วคำตอบของ Eric มีประโยชน์และทั้งหมดนี้ แต่ไม่ได้ตอบคำถามที่แท้จริงเกี่ยวกับวิธีการทดสอบโดยใช้ประเภทที่ไม่รู้จักในลักษณะ "u is t" ที่อธิบายไว้ในคำถามเดิมและของคุณตอบ
Daniel

@ แดเนียล - ไม่เป๊ะ คำตอบของ Dave นั้นถูกต้องก็ต่อเมื่อคุณต้องการยกเว้นคลาสย่อยของ t คำตอบของ Eric ส่วนใหญ่อธิบายว่าต้องทำอย่างไร มันเป็นเพียงการชี้แจงว่าจะวาง "t" ไว้ที่ใด ฉันจะเพิ่มความคิดเห็นที่นั่น
ToolmakerSteve

10

คุณต้องดูว่าประเภทของอินสแตนซ์ของคุณเท่ากับประเภทของคลาสหรือไม่ ในการรับประเภทของอินสแตนซ์คุณใช้GetType()วิธีการ:

 u.GetType().Equals(t);

หรือ

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

ควรทำ เห็นได้ชัดว่าคุณสามารถใช้ '==' เพื่อทำการเปรียบเทียบได้หากต้องการ


+1 แต่ชอบทางเลือกที่สองมากกว่า u.GetType.Equals(typeof(User));
Omar

เหตุผลหนึ่งที่ปลอดภัยน้อยกว่าการใช้ == - ก็คือถ้า GetType () คืนค่า null มันจะโยน
Dave Bish

1
@Fuex ใช่ฉันคิดว่ามันทำให้โค้ดอ่านง่ายขึ้นถ้า typeof เป็นแบบอินไลน์ซึ่งเป็นสาเหตุที่ฉันโพสต์แบบนั้นแม้ว่าในตัวอย่าง OPs เขาจะมีตัวแปรtที่มีประเภทอยู่แล้วก็ตาม
Sam Holder

@DaveBish ถ้า GetType ส่งคืนโมฆะฉันก็จะกังวลว่าหลายสิ่งหลายอย่างจะเริ่มโยน ... แต่ชี้ไปแล้วคุณพูดถูกแน่นอน
Sam Holder

@SamHolder Yeah - สถานการณ์เดียวที่จะเกิดขึ้นคือถ้ามีใครบางคนลบล้างประเภทพื้นฐานและทำให้การใช้งานผิดพลาด มันจะแปลกอย่างแน่นอน
Dave Bish

4

เพื่อตรวจสอบว่าวัตถุเข้ากันได้กับตัวแปรชนิดที่กำหนดหรือไม่แทนที่จะเขียน

u is t

คุณควรเขียน

typeof(t).IsInstanceOfType(u)

1
ประโยชน์ของไวยากรณ์ verbose มากกว่ากับไวยากรณ์ 'u is t' คืออะไร?
Kyle Humfeld

@KyleHumfeld ถ้าคุณมีพิมพ์ foo; วัตถุ A; คุณไม่สามารถเขียน "A is foo" แต่คุณสามารถเขียน foo.isInstanceOfType (A)
Timur Nuriyasov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.