Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
นี่เป็นข้อผิดพลาด ตัวดำเนินการ typeof ใน C # สามารถใช้ชื่อประเภทได้เท่านั้นไม่ใช่วัตถุ
if (obj1.GetType() == typeof(int))
// Some code here
สิ่งนี้จะได้ผล แต่อาจไม่เป็นอย่างที่คุณคาดหวัง สำหรับประเภทค่าตามที่คุณแสดงไว้ที่นี่เป็นที่ยอมรับ แต่สำหรับประเภทอ้างอิงมันจะคืนค่าจริงถ้าประเภทนั้นเป็นประเภทเดียวกันแน่นอนไม่ใช่อย่างอื่นในลำดับชั้นการสืบทอด ตัวอย่างเช่น
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");
}
นี้จะพิมพ์"o is something else"
เพราะประเภทของการo
เป็นไม่ได้Dog
Animal
คุณสามารถใช้งานได้อย่างไรก็ตามหากคุณใช้IsAssignableFrom
วิธีการType
เรียน
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
เทคนิคนี้ยังคงเป็นปัญหาสำคัญอยู่ ถ้าตัวแปรของคุณเป็นโมฆะการเรียกไปGetType()
จะส่ง NullReferenceException ดังนั้นเพื่อให้ทำงานได้อย่างถูกต้องคุณต้อง:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
ด้วยสิ่งนี้คุณมีพฤติกรรมที่เท่าเทียมกันของis
คำหลัก ดังนั้นหากนี่เป็นพฤติกรรมที่คุณต้องการคุณควรใช้is
คำหลักที่อ่านได้ง่ายและมีประสิทธิภาพมากขึ้น
if(o is Animal)
Console.WriteLine("o is an animal");
ในกรณีส่วนใหญ่is
คำหลักนั้นยังคงไม่ใช่สิ่งที่คุณต้องการเพราะปกติแล้วมันจะไม่เพียงพอที่จะรู้ว่าวัตถุนั้นเป็นประเภทใด โดยปกติแล้วคุณต้องการใช้วัตถุนั้นเป็นอินสแตนซ์ของประเภทนั้นซึ่งต้องใช้การคัดเลือกวัตถุด้วย ดังนั้นคุณอาจพบว่าคุณเขียนโค้ดเช่นนี้:
if(o is Animal)
((Animal)o).Speak();
แต่นั่นทำให้ CLR ตรวจสอบประเภทของวัตถุได้ถึงสองครั้ง มันจะตรวจสอบอีกครั้งเพื่อตอบสนองis
ผู้ใช้งานและหากo
เป็นจริงAnimal
เราจะทำการตรวจสอบอีกครั้งเพื่อตรวจสอบการหล่อ
การทำเช่นนี้มีประสิทธิภาพมากกว่าแทน:
Animal a = o as Animal;
if(a != null)
a.Speak();
ผู้ประกอบการเป็นนักแสดงที่จะไม่โยนยกเว้นถ้ามันล้มเหลวแทนที่จะกลับas
null
ด้วยวิธีนี้ CLR จะตรวจสอบประเภทของวัตถุเพียงครั้งเดียวและหลังจากนั้นเราต้องทำการตรวจสอบแบบ null ซึ่งมีประสิทธิภาพมากขึ้น
แต่ระวัง: as
หลายคนตกอยู่ในกับดักด้วย เพราะมันไม่ได้ส่งข้อยกเว้นบางคนคิดว่ามันเป็นนักแสดงที่ "ปลอดภัย" และพวกเขาใช้มันเป็นแบบปกติ สิ่งนี้นำไปสู่ข้อผิดพลาดเช่นนี้:
(o as Animal).Speak();
ในกรณีนี้ผู้พัฒนาคาดว่าo
จะเป็นเสมอAnimal
และตราบใดที่ข้อสันนิษฐานของพวกเขาถูกต้องทุกอย่างก็ใช้ได้ดี NullReferenceException
แต่ถ้าพวกเขากำลังที่ไม่ถูกต้องแล้วสิ่งที่พวกเขาจบลงด้วยการที่นี่เป็น ด้วยการร่ายปกติพวกเขาจะได้รับการInvalidCastException
แทนที่ซึ่งจะระบุปัญหาได้อย่างถูกต้องมากขึ้น
บางครั้งข้อผิดพลาดนี้อาจหายาก:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
นี่เป็นอีกกรณีหนึ่งที่ผู้พัฒนาคาดว่าo
จะชัดเจนAnimal
ทุกครั้ง แต่นี่ไม่ชัดเจนในตัวสร้างที่as
นักแสดงใช้ ไม่ชัดเจนจนกว่าคุณจะไปถึงInteract
วิธีที่animal
คาดว่าจะได้รับการกำหนดเขตบวก ในกรณีนี้ไม่เพียง แต่คุณจะจบลงด้วยข้อยกเว้นที่ทำให้เข้าใจผิด แต่จะไม่ถูกโยนทิ้งจนกว่าจะเกิดข้อผิดพลาดที่เกิดขึ้นจริง
สรุป:
หากคุณจำเป็นต้องรู้ว่าวัตถุมีประเภทให้ใช้is
หรือไม่
หากคุณต้องการที่จะรักษาวัตถุเป็นตัวอย่างของบางประเภท แต่คุณไม่ทราบว่าวัตถุจะเป็นประเภทที่ใช้และตรวจสอบas
null
หากคุณต้องการปฏิบัติต่อวัตถุเป็นตัวอย่างของบางประเภทและวัตถุนั้นควรจะเป็นประเภทนั้นให้ใช้การร่ายปกติ
as
!