มีวิธีทดสอบว่า T สืบทอด / ใช้คลาส / อินเทอร์เฟซหรือไม่?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
มีวิธีทดสอบว่า T สืบทอด / ใช้คลาส / อินเทอร์เฟซหรือไม่?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
คำตอบ:
มีวิธีการที่เรียกว่าเป็นType.IsAssignableFrom ()
วิธีตรวจสอบว่าT
สืบทอด / ดำเนินการหรือไม่Employee
:
typeof(Employee).IsAssignableFrom(typeof(T));
หากคุณกำหนดเป้าหมาย. NET Core วิธีนี้ได้ย้ายไปที่ TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits U
แปลเป็นtypeof(T).IsAssignableFrom(typeof(U))
.
T
ถูก จำกัด ให้เป็นประเภทอื่นTOther
เมื่อดำเนินการแล้วtypeof(T)
จะประเมินเป็นจริงtypeof(TOther)
ไม่ใช่ประเภทใดก็ตามที่T
คุณผ่านมาจริงและในกรณีนั้นtypeof(SomeInterface).IsAssignableFrom(typeof(T))
จะล้มเหลว (โดยถือว่าTOther
ไม่ได้ใช้งานด้วยSomeInterface
) แม้ว่าประเภทคอนกรีตของคุณจะใช้งานSomeInterface
ได้
IsAssignableFrom
ของTypeInfo
class ยอมรับเฉพาะ TypeInfo เนื่องจากเป็นอาร์กิวเมนต์เท่านั้นดังนั้นตัวอย่างควรเป็นดังนี้:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
คุณสามารถใช้ข้อ จำกัด ในชั้นเรียน
MyClass<T> where T : Employee
ลองดูที่http://msdn.microsoft.com/en-us/library/d5x73970.aspx
หากคุณต้องการตรวจสอบระหว่างการคอมไพล์: เกิดข้อผิดพลาดหากT
ไม่ใช้อินเตอร์เฟส / คลาสที่ต้องการคุณสามารถใช้ข้อ จำกัด ต่อไปนี้
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
ฉันหวังว่าจะช่วยได้
ไวยากรณ์ที่ถูกต้องคือ
typeof(Employee).IsAssignableFrom(typeof(T))
ค่าส่งกลับ:
true
ถ้าc
และปัจจุบันType
เป็นตัวแทนประเภทเดียวกันหรือถ้ากระแสType
อยู่ในลำดับชั้นการสืบทอดของc
หรือถ้ากระแสType
เป็นสิ่งinterface
ที่c
ดำเนินการหรือถ้าc
เป็นพารามิเตอร์ประเภททั่วไปและปัจจุบันType
แสดงถึงข้อ จำกัด อย่างใดอย่างหนึ่งของc
หรือ ถ้าc
แสดงถึงชนิดค่าและปัจจุบันType
แสดงNullable<c>
(Nullable(Of c)
ใน Visual Basic)false
ถ้าไม่มีเงื่อนไขเหล่านี้true
หรือถ้ามีc
null
หากEmployee IsAssignableFrom T
แล้วสืบทอดจากT
Employee
การใช้งาน
typeof(T).IsAssignableFrom(typeof(Employee))
ส่งคืนtrue
ก็ต่อเมื่ออย่างใดอย่างหนึ่ง
T
และEmployee
เป็นตัวแทนประเภทเดียวกัน หรือ,Employee
สืบทอดมาจากT
.นี่อาจเป็นการใช้งานตามวัตถุประสงค์ในบางกรณี แต่สำหรับคำถามเดิม (และการใช้งานทั่วไป) เพื่อพิจารณาว่าเมื่อใดที่T
สืบทอดหรือดำเนินการclass
/ interface
ใช้:
typeof(Employee).IsAssignableFrom(typeof(T))
สิ่งที่ทุกคนหมายถึงคือ:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
เพราะคุณสามารถกำหนดจากอินสแตนซ์ของ a DerivedType
ไปยังอินสแตนซ์ของBaseType
:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
เมื่อไหร่
public class BaseType {}
public class DerivedType : BaseType {}
และตัวอย่างที่เป็นรูปธรรมหากคุณมีปัญหาในการพันศีรษะ:
(ผ่าน LinqPad ด้วยเหตุนี้HorizontalRun
และDump
)
void Main()
{
// http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface
var b1 = new BaseClass1();
var c1 = new ChildClass1();
var c2 = new ChildClass2();
var nb = new nobase();
Util.HorizontalRun(
"baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
b1.IsAssignableFrom(typeof(BaseClass1)),
c1.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass1)),
c2.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(ChildClass2)),
nb.IsAssignableFrom(typeof(BaseClass1)),
b1.IsAssignableFrom(typeof(nobase))
).Dump("Results");
var results = new List<string>();
string test;
test = "c1 = b1";
try {
c1 = (ChildClass1) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c1";
try {
b1 = c1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "c2 = b1";
try {
c2 = (ChildClass2) b1;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
test = "b1 = c2";
try {
b1 = c2;
results.Add(test);
} catch { results.Add("FAIL: " + test); }
results.Dump();
}
// Define other methods and classes here
public static class exts {
public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
return typeof(T).IsAssignableFrom(baseType);
}
}
class BaseClass1 {
public int id;
}
class ChildClass1 : BaseClass1 {
public string name;
}
class ChildClass2 : ChildClass1 {
public string descr;
}
class nobase {
public int id;
public string name;
public string descr;
}
ชั้นฐาน -> ชั้นฐาน
จริง
child1-> baseclass
เท็จ
baseclass-> child1
จริง
child2-> baseclass
เท็จ
baseclass-> child2
จริง
nobase-> เบสคลาส
เท็จ
baseclass-> nobase
เท็จ
และ
- ความล้มเหลว: c1 = b1
- b1 = c1
- ล้มเหลว: c2 = b1
- b1 = c2
ฉันเชื่อว่าไวยากรณ์คือ: typeof(Employee).IsAssignableFrom(typeof(T));
แม้ว่า IsAssignableFrom จะเป็นวิธีที่ดีที่สุดตามที่ผู้อื่นระบุไว้ แต่หากคุณต้องการตรวจสอบว่าคลาสที่สืบทอดมาจากคลาสอื่นtypeof(T).BaseType == typeof(SomeClass)
ก็จะทำงานได้เช่นกัน
SomeClass
BaseClass
วิธีอื่นในการบอกว่าอ็อบเจ็กต์o
สืบทอดคลาสหรือใช้อินเทอร์เฟซคือการใช้ตัวดำเนินการis
และas
หากคุณต้องการทราบเฉพาะว่าอ็อบเจ็กต์สืบทอดคลาสหรือใช้อินเทอร์เฟซตัวis
ดำเนินการจะส่งคืนผลลัพธ์บูลีน:
bool isCompatibleType = (o is BaseType || o is IInterface);
หากคุณต้องการใช้คลาสที่สืบทอดมาหรืออินเทอร์เฟซที่นำมาใช้หลังจากการทดสอบของคุณas
โอเปอเรเตอร์จะทำการแคสต์ที่ปลอดภัยโดยส่งคืนการอ้างอิงไปยังคลาสที่สืบทอดมาหรืออินเทอร์เฟซที่ใช้งานหากเข้ากันได้หรือเป็นโมฆะหากไม่เข้ากัน
BaseType b = o as BaseType; // Null if d does not inherit from BaseType.
IInterface i = o as IInterface; // Null if d does not implement IInterface.
หากคุณมีเพียงประเภทT
ให้ใช้คำตอบของ @ nikeee