检查“ T”是否继承或实现了类/接口


92

有没有一种方法可以测试T是否继承/实现一个类/接口?

private void MyGenericClass<T> ()
{
    if(T ... inherits or implements some class/interface
}

4
这似乎可行... if(typeof(TestClass).IsAssignableFrom(typeof(T))),有人可以证实我的怀疑吗?谢谢!
user1229895

我绝对肯定这个答案会重复很多次!
Felix K.

3
Felix K即使这个答案已经被重复很多次了,但很多时候对很多人也有帮助;)...五分钟前像我一样:)
塞缪尔(Samuel)

Answers:


136

有一个称为Type.IsAssignableFrom()的方法

要检查是否T继承/实现Employee

typeof(Employee).IsAssignableFrom(typeof(T));

如果您以.NET Core为目标,则该方法已移至TypeInfo:

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())

您应该使用示例更新您的答案,例如typeof(T).IsAssignableFrom(typeof(IMyInterface))
Andrew Burnett-Thompson博士

没做过耐克;旧的答案仍然存在。:)我花了几秒钟来找出问题所在。无论如何,.net框架还是+1的一个不错的功能。
塞缪尔

实际上,您提到的方式是我前一段时间的方式。我纠正了这个。请参阅以前的评论。T inherits U实际上转换为typeof(T).IsAssignableFrom(typeof(U))
nikeee 2014年

2
尽管这几乎可行,但是存在一个问题,如果T被约束为其他类型TOther,则在执行时,typeof(T)将实际求值,typeof(TOther)而不是T您实际传递的任何类型,在这种情况下,typeof(SomeInterface).IsAssignableFrom(typeof(T))将失败(假设TOther也未实现SomeInterface),即使您的具体类型确实实现了SomeInterface
Dave Cousineau

1
在.net核心中IsAssignableFromTypeInfo类的唯一参数仅接受TypeInfo,因此示例应为以下内容:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
至2016年


16

如果你想在编译期间检查:如果出现错误,如果T 实现所需的接口/类,你可以使用下面的约束

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

希望对您有所帮助。


12

正确的语法是

typeof(Employee).IsAssignableFrom(typeof(T))

文献资料

返回值: true如果c与当前Type表示相同的类型,或者如果当前Type是在继承层次结构c,或者如果当前Typeinterfacec器具,或者,如果c是一个通用的类型参数和当前Type表示的约束之一c,或if c表示值类型,而current Type表示Nullable<c>Nullable(Of c)在Visual Basic中)。false如果这些条件都不是true,或者cnull

资源

说明

如果Employee IsAssignableFrom TT从继承Employee

用法

typeof(T).IsAssignableFrom(typeof(Employee)) 

true 在以下任一情况下返回

  1. TEmployee代表相同的类型;要么,
  2. Employee继承自T

某些情况下,这可能是预期的用法,但对于原始问题(以及更常见的用法),确定何时T继承或实现某些class/ interface,请使用:

typeof(Employee).IsAssignableFrom(typeof(T))

9

每个人真正的意思是:

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,因此通过HorizontalRunDump

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


0

尽管IsAssignableFrom是其他人所说的最好的方法,但是如果您只需要检查一个类是否继承自另一个类,typeof(T).BaseType == typeof(SomeClass)则也可以执行此操作。


除非SomeClass不是直接来自,否则该方法有效BaseClass
Suncat2000

0

判断对象是o继承类还是实现接口的另一种方法是使用isand 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的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.