ตรวจสอบว่าอินสแตนซ์เป็นประเภท


181

ใช้นี้เพื่อตรวจสอบว่าเป็นตัวอย่างของcTForm

c.GetType().Name.CompareTo("TForm") == 0

มีวิธีที่ปลอดภัยกว่าที่จะทำนอกเหนือจากการใช้stringparam เป็นCompareTo()หรือไม่?


20
ฉันหวังว่าคุณจะไม่ทำอย่างนั้นใน Java เช่นกัน Java instanceofและ C # isเป็นวิธีที่ดีกว่าในการทำเช่นนั้น
Powerlord

คำตอบ:


410

คำตอบที่ต่างกันที่นี่มีความหมายต่างกันสองแบบ

หากคุณต้องการตรวจสอบว่าอินสแตนซ์เป็นประเภทที่แน่นอนแล้ว

if (c.GetType() == typeof(TForm))

เป็นวิธีที่จะไป

หากคุณต้องการทราบว่าcเป็นอินสแตนซ์ของTForm หรือคลาสย่อยให้ใช้is/ as:

if (c is TForm)

หรือ

TForm form = c as TForm;
if (form != null)

มันคุ้มค่าที่จะต้องทราบชัดเจนว่าคุณต้องการพฤติกรรมแบบใด


7
หมายเหตุเล็ก ๆ : ใช้ "คือ" ถ้าคุณไม่ต้องการใช้ผลลัพธ์ของการส่งและใช้ "เป็น" ถ้าคุณทำ
Aviram Fireberger

14
ด้วย C # 7 คุณสามารถรวมisและasมีการจับคู่แบบ:if (x is TForm tf) {…
ริชาร์ด

39
if(c is TFrom)
{
   // Do Stuff
}

หรือถ้าคุณวางแผนที่จะใช้cเป็น a TFormใช้ตัวอย่างต่อไปนี้:

var tForm = c as TForm;
if(tForm != null)
{
   // c is of type TForm
}

ตัวอย่างที่สองจำเป็นต้องตรวจสอบเพื่อดูว่าcเป็นประเภทTFormหนึ่งครั้ง โดยที่ถ้าคุณตรวจสอบว่าดูว่าcเป็นประเภทTFormไหนแล้วนำไปทิ้ง CLR จะได้รับการตรวจสอบพิเศษ นี่คือการอ้างอิง

แก้ไข: ขโมยจาก Jon Skeet

หากคุณต้องการให้แน่ใจว่าcเป็นของTFormและไม่ใช่คลาสที่สืบทอดมาTFormให้ใช้

if(c.GetType() == typeof(TForm))
{
   // Do stuff cause c is of type TForm and nothing else
}

14

ใช่คำหลัก "เป็น":

if (c is TForm)
{
    ...
}

ดูรายละเอียดเกี่ยวกับ MSDN: http://msdn.microsoft.com/en-us/library/scekt9xw(VS.80).aspx

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


10

นอกจากนี้ค่อนข้างอยู่ในหลอดเลือดดำเดียวกัน

Type.IsAssignableFrom(Type c)

"เป็นจริงถ้า c และชนิดปัจจุบันแสดงถึงชนิดเดียวกันหรือถ้าประเภทปัจจุบันอยู่ในลำดับชั้นการสืบทอดของ c หรือถ้าชนิดปัจจุบันเป็นอินเทอร์เฟซที่ c ใช้หรือถ้า c เป็นพารามิเตอร์ชนิดทั่วไปและชนิดปัจจุบัน หมายถึงหนึ่งในข้อ จำกัด ของ c "

จากที่นี่: http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx


นี่คือสิ่งที่ฉันชอบส่วนตัว typeof(Class).IsAssignableFrom(object.getType())คล้ายกับตัวinstanceofดำเนินการJava
SkidRunner

มันให้เท็จถ้าพวกเขาไม่ได้อยู่ในสาขาเดียวกันของลำดับชั้นการสืบทอด แต่มีผู้ดำเนินการแปลงอยู่หรือไม่?
Paul Stelian

เป็นคำถามที่ดี @ PaulStelian ฉันไม่แน่ใจว่าอยู่ด้านบนของหัวของฉัน แต่ฉันเดาว่ามันจะกลับมาเป็นเท็จในสถานการณ์นั้น อย่างน้อยก็น่าจะเป็นพฤติกรรมที่ฉันคาดหวัง อาจเป็นไปได้ว่ามีการแปลงโดยปริยายมันอาจจะกลับมาจริง
แบรดคัน

ทุกคนที่มี Visual Studio ติดตั้งให้ลองใช้หรือไม่
Paul Stelian

1
@PaulStelian - มันคืนค่าเท็จ สามารถดูได้โดยติดตามลิงก์ doc และการสังเกตไม่มีการพูดถึงการแปลง อีกวิธีในการคิดเกี่ยวกับมันคือการT1.IsAssignableFrom(T2)ส่งคืนtrueในสถานการณ์ที่ตัวasดำเนินการส่งคืนค่าที่ไม่ใช่ค่า null ซึ่งกำหนดอินสแตนซ์ของประเภทเหล่านั้น
ToolmakerSteve



2

ดังที่คนอื่น ๆ พูดถึงคำหลัก "คือ" อย่างไรก็ตามหากคุณจะโยนมันในภายหลังในประเภทนั้นเช่น

TForm t = (TForm)c;

จากนั้นคุณควรใช้คำว่า "เป็น"

เช่น TForm t = c as TForm.

จากนั้นคุณสามารถตรวจสอบ

if(t != null)
{
 // put TForm specific stuff here
}

อย่ารวมเช่นเดียวกับเนื่องจากเป็นเช็คที่ซ้ำกัน



-1
bool isValid = c.GetType() == typeof(TForm) ? true : false;

หรือเรียบง่าย

bool isValid = c.GetType() == typeof(TForm);

IMHO: ฉันจะหลีกเลี่ยงความเห็นอกเห็นใจโดยตรง (เช่น==) ในภาษาเชิงวัตถุหรือภาษาที่สนับสนุนการสืบทอดเว้นแต่คุณจะรู้ว่าประเภทเฉพาะของคุณจะไม่ถูกสืบทอดจากเช่นsealedคลาส นอกจากนี้: การใช้งานของผู้ประกอบการที่ประกอบไปด้วยกลับ (คงที่ / คงที่) ค่าบูลีนรบกวนจิตใจผมผมจะได้รับการใส่ใจน้อยถ้ามันเป็นswitchคำสั่ง
SkidRunner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.