【问题标题】:Check if 'T' inherits or implements a class/interface检查'T'是否继承或实现了一个类/接口
【发布时间】:2012-05-29 21:47:44
【问题描述】:

有没有办法测试 T 是否继承/实现了一个类/接口?

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

【问题讨论】:

  • 这似乎有效......如果(typeof(TestClass).IsAssignableFrom(typeof(T))),有人可以证实我的怀疑吗?谢谢!
  • 我绝对肯定这个答案被重复了很多次!
  • Felix K 即使这个答案被重复了很多次,它也帮助了很多人很多次;)......就像我五分钟前:)

标签: c# generics


【解决方案1】:

有一个方法叫做Type.IsAssignableFrom()

检查T是否继承/实现Employee

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

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

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

请注意,如果您想限制您的类型 T 以实现某个接口或从某个类继承,您应该选择@snajahi 的答案,它使用编译时检查,通常类似于解决此问题的更好方法.

【讨论】:

  • 你应该用一个例子来更新你的答案,例如typeof(T).IsAssignableFrom(typeof(IMyInterface))
  • 未完成 nikeee;旧答案仍然存在。 :) 我花了几秒钟才弄清楚出了什么问题。无论如何,+1,.net 框架的又一个不错的功能。
  • 其实你说的方式就是我前段时间的方式。我纠正了这个。请参阅以前的 cmets。 T inherits U 实际上转换为 typeof(T).IsAssignableFrom(typeof(U))
  • 虽然这几乎可行,但存在一个问题,如果 T 被限制为其他类型 TOther,那么在执行时,typeof(T) 实际上将评估为 typeof(TOther) 而不是任何类型T 你实际上已经通过了,在这种情况下,typeof(SomeInterface).IsAssignableFrom(typeof(T)) 将失败(假设 TOther 也没有实现 SomeInterface),即使你的具体类型确实实现了 SomeInterface
  • 在 .net core IsAssignableFrom of TypeInfo 类中只接受 TypeInfo 作为它的唯一参数,因此示例应该如下:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
【解决方案2】:

您可以对类使用约束。

MyClass<T> where T : Employee

看看http://msdn.microsoft.com/en-us/library/d5x73970.aspx

【讨论】:

    【解决方案3】:

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

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

    希望对你有帮助。

    【讨论】:

      【解决方案4】:

      正确的语法是

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

      文档

      返回值: true 如果c 和当前Type 表示相同类型,或者如果当前Typec 的继承层次结构中,或者如果当前的Typec 实现的interface,或者如果c 是泛型类型参数并且当前Type 表示c 的约束之一,或者如果c 表示一个值类型和当前Type 代表Nullable&lt;c&gt;(在Visual Basic 中为Nullable(Of c))。 false 如果这些条件都不是true,或者如果cnull

      source

      说明

      如果Employee IsAssignableFrom TT 继承自Employee

      用法

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

      返回true

      1. TEmployee 代表同一类型;或者,
      2. Employee 继承自 T

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

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

      【讨论】:

        【解决方案5】:

        每个人真正的意思是:

        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->基类

        错误

        基类->child1

        是的

        child2->基类

        错误

        基类->child2

        是的

        nobase->基类

        错误

        基类->nobase

        错误

        • 失败:c1 = b1
        • b1 = c1
        • 失败:c2 = b1
        • b1 = c2

        【讨论】:

          【解决方案6】:

          我相信语法是:typeof(Employee).IsAssignableFrom(typeof(T));

          【讨论】:

          • 这是预期的语法。 +1
          【解决方案7】:

          虽然正如其他人所说,IsAssignableFrom 是最好的方法,但如果您只需要检查一个类是否从另一个类继承,typeof(T).BaseType == typeof(SomeClass) 也可以完成这项工作。

          【讨论】:

          • 除非SomeClass 不是直接从BaseClass 派生的,否则该方法有效。
          【解决方案8】:

          判断对象o是继承类还是实现接口的另一种方法是使用isas运算符。

          如果你只想知道一个对象是继承了一个类还是实现了一个接口,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.
          

          如果您只有T 类型,请使用@nikeee 的答案。

          【讨论】:

            猜你喜欢
            • 2016-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-21
            • 1970-01-01
            • 1970-01-01
            • 2023-03-22
            相关资源
            最近更新 更多