อะไรคือความแตกต่างระหว่าง System.Type และ System.RuntimeType ใน C #?


90

วันนี้ฉันพยายามทำแบบทดสอบการประชุมและรับทุกประเภทในการประชุม (โดยการโทรAssembly.GetTypes()) เมื่อฉันสะดุดอะไรบางอย่าง:

System.RuntimeType:[First.Namespace.FirstClass]

เมื่อใดก็ตามที่ฉันพยายามเปรียบเทียบประเภทtypeof(FirstClass)นั้นมันไม่เท่ากัน ดังนั้นเมื่อฉันพยายามค้นหาทุกประเภทที่มีFirstClassเป็นพารามิเตอร์ทั่วไปฉันไม่พบเลย

อะไรคือความแตกต่างระหว่างSystem.RuntimeTypeและSystem.Type?

มีวิธีใดในการแก้ปัญหาของฉันหรือไม่?


6
คุณสามารถจัดหาโปรแกรมขนาดเล็กที่แสดงถึงปัญหาที่คุณประสบได้หรือไม่?
Eric Lippert

ฉันจะไป แต่ได้รับคำตอบแล้ว: P
Edgar Gonzalez

คำตอบ:


109

System.RuntimeTypeSystem.Typeเป็นชั้นที่เป็นรูปธรรมที่เกิดขึ้นจากชั้นฐานนามธรรม เนื่องจากไม่ได้เป็นที่สาธารณะที่คุณมักจะพบกรณีมันเป็นSystem.RuntimeTypeSystem.Type

ความสับสนอาจเกิดขึ้นได้เมื่อคุณพยายามหาประเภทของวัตถุและเรียกGetType()ใช้วัตถุอื่นที่แสดงประเภทของวัตถุแรกโดยไม่ถูกต้องแทนที่จะใช้วัตถุนั้นโดยตรง จากนั้นType.ToString()จะกลับมา"System.RuntimeType"เมื่อวัตถุถูกเรียกใช้เป็นตัวแทนประเภท:

string str = string.Empty;
Type strType = str.GetType();
Type strTypeType = strType.GetType();
strType.ToString();     // returns "System.string"
strTypeType.ToString(); // returns "System.RuntimeType"

ตัวอย่างเช่นในบล็อกโพสต์นี้มีคนพยายามหาประเภทของคอลัมน์ในฐานข้อมูลโดยทำสิ่งนี้:

object val = reader.GetFieldType(index);
Type runtimeType = val.GetType();
PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
Type type = (Type)propInfo.GetValue(val, null);

เนื่องจาก val เป็นอ็อบเจ็กต์ Type อยู่แล้ว val.GetType () จะส่งคืนอ็อบเจ็กต์ Type อื่นที่แสดงประเภทSystem.RuntimeTimeเนื่องจากเป็นชนิดคอนกรีตที่ใช้แทนอ็อบเจ็กต์ประเภทดั้งเดิม จากนั้นบล็อกโพสต์จะแสดงกลอุบายการสะท้อนที่ไม่จำเป็นเพื่อให้ได้ประเภทของวัตถุประเภทดั้งเดิมเมื่อสิ่งที่ต้องการจริงๆคือ:

Type type = reader.GetFieldType(index) as Type;

ดังนั้นหากคุณ Typeออบเจ็กต์กำลังรายงานว่ามันแสดงถึง a System.RuntimeTypeตรวจสอบให้แน่ใจว่าคุณไม่ได้เรียกGetType()ประเภทที่คุณมีอยู่แล้วโดยไม่ได้ตั้งใจ


ข้อมูลโค้ดแรกจะตรวจสอบว่าออบเจ็กต์เป็นอินสแตนซ์Typeเท่านั้นหรือไม่ซึ่งจะส่งคืนจริงแม้ว่าคุณจะผ่านtypeof(int)ก็ตาม ข้อมูลโค้ดสองไม่ทำงานสำหรับการเปรียบเทียบและtypeof(string).GetType() typeof(Type)
Mark Cidade

นี่คือสิ่งที่ฉันกำลังมองหา! ฉันพบโพสต์ของ Thomas Danecker แต่ไม่ใช่ของ Doogal Bell
Edgar Gonzalez

1
@ มาร์คซิเดด. เห็นดีขอบคุณ มีคำตอบที่ตายตัวเพื่อเป็นประโยชน์มากขึ้นหวังว่าจะช่วยขจัดความสับสนที่ฉันแนะนำโดยอ้างถึงบล็อกโพสต์นั้น
Ergwun

@Edgar Gonzalez: บล็อกโพสต์ที่ฉันอ้างถึงนั้นค่อนข้างทำให้เข้าใจผิด โปรดดูคำตอบที่อัปเดตของฉันสำหรับข้อมูลที่ดีขึ้น
Ergwun

4

จากคำตอบของDifferent ระหว่าง System.Type และ System.RuntimeTypeโดยThomas Danecker :

System.Type เป็นคลาสฐานนามธรรม CLR มีการนำไปใช้อย่างเป็นรูปธรรมในประเภท System.RuntimeType ภายใน เนื่องจาก typeof นี้ (สตริง) .GetType () ส่งกลับ RuntimeType แต่ typeof (Type) ส่งคืน Type ปกติ การใช้เมธอด. Equals เป็น object.ReferenceEquals ซึ่งส่งคืนค่าเท็จ เพื่อให้ได้ผลลัพธ์ที่คาดหวังคุณอาจใช้ type.IsInstanceOfType (องค์ประกอบ) สิ่งนี้จะส่งคืนจริงหากองค์ประกอบเป็นประเภทที่ได้รับ หากคุณต้องการตรวจสอบประเภทที่แน่นอนผลตอบแทนที่เป็นเท็จของวิธีการของคุณคือผลลัพธ์ที่ต้องการ คุณยังสามารถใช้ checkType (arrayType, Type.GetType ("System.RuntimeType")) เพื่อตรวจสอบ RuntimeType


1
"does in fact an" - เราจะแก้ไขไวยากรณ์ได้ไหม นี่เป็นเหมือนปมของเรื่องทั้งหมดและมันไม่สมเหตุสมผล
N73k

2

โดยสังเขป ...

    "".GetType().ToString()           == "System.String"

    "".GetType().GetType().ToString() == "System.RuntimeType"

วิธีการที่ตอนนี้ฉันคิดเกี่ยวกับมันก็คือว่าเป็นชนิดฐานสำหรับประเภทที่แสดงถึงผลการร้องขอชนิดของวัตถุที่รันไทม์คือSystem.Type System.RuntimeTypeดังนั้นเมื่อคุณขอประเภทของวัตถุเช่นใน"".GetType()ตัวอย่างของสิ่งที่System.Typeส่งคืนจะลดหลั่นSystem.RuntimeTypeกันไป ในความเป็นจริงเราควรคาดหวังว่ามันtypeof(System.Type).GetType()ควรจะSystem.RuntimeTypeเป็นเช่นกัน แต่ฉันคิดว่ากรอบนี้ป้องกันสิ่งนี้โดยเฉพาะ ... ความสมมาตร


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.