有没有一种方法可以测试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
}
Answers:
有一个称为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
类的唯一参数仅接受TypeInfo,因此示例应为以下内容:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
正确的语法是
typeof(Employee).IsAssignableFrom(typeof(T))
返回值:
true
如果c
与当前Type
表示相同的类型,或者如果当前Type
是在继承层次结构c
,或者如果当前Type
是interface
那c
器具,或者,如果c
是一个通用的类型参数和当前Type
表示的约束之一c
,或ifc
表示值类型,而currentType
表示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
因为您可以从字面上的实例分配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-> child2
真正
nobase-> baseclass
假
baseclass-> nobase
假
和
- 失败:c1 = b1
- b1 = c1
- 失败:c2 = b1
- b1 = c2
尽管IsAssignableFrom是其他人所说的最好的方法,但是如果您只需要检查一个类是否继承自另一个类,typeof(T).BaseType == typeof(SomeClass)
则也可以执行此操作。
SomeClass
不是直接来自,否则该方法有效BaseClass
。
判断对象是o
继承类还是实现接口的另一种方法是使用is
and as
运算符。
如果仅想知道对象是继承类还是实现接口,则is
运算符将返回布尔结果:
bool isCompatibleType = (o is BaseType || o is IInterface);
如果要在测试后使用继承的类或实现的接口,则as
操作员将执行安全的强制转换,如果兼容,则返回对继承的类或实现的接口的引用;如果不兼容,则返回null:
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.
如果只有type T
,则使用@nikeee的答案。