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
หากคุณต้องการให้วัตถุเป็นอินสแตนซ์ประเภทใดประเภทหนึ่ง และวัตถุนั้นควรจะเป็นประเภทนั้น ให้ใช้การส่งแบบปกติ
person
P Daddy
schedule
11.06.2009
as
! - person RCIX   schedule 08.10.2009as
ไม่ใช่การตรวจสอบประเภทจริงๆ นะ... - person jasonh   schedule 08.10.2009as
เป็นรูปแบบหนึ่งของการตรวจสอบประเภทอย่างแน่นอน มากพอๆ กับis
ที่เป็น! โดยจะใช้is
เบื้องหลังอย่างมีประสิทธิภาพ และใช้ทั่วทั้ง MSDN ในตำแหน่งที่ปรับปรุงความสะอาดของโค้ดเทียบกับis
แทนที่จะตรวจสอบis
ก่อน การเรียกas
จะสร้างตัวแปรที่พิมพ์ไว้ซึ่งพร้อมใช้งาน: ถ้าเป็น null ให้ตอบสนองอย่างเหมาะสม มิฉะนั้นให้ดำเนินการต่อ แน่นอนสิ่งที่ฉันได้เห็นและใช้ไม่น้อย - person Zaccone   schedule 20.08.2014as
/is
(ครอบคลุมอยู่ใน stackoverflow.com/a/27813381/477420) โดยถือว่า ความหมายทำงานสำหรับกรณีของคุณ - person Alexei Levenkov   schedule 07.01.2015GetType
ที่คุณเชื่อมโยงอยู่ในSystem.Reflection.Assembly
-- วิธีการที่แตกต่างไปจากเดิมอย่างสิ้นเชิงและไม่เกี่ยวข้องกับที่นี่ - person Kirk Woll   schedule 11.08.2017