【问题标题】:How to determine if an object inherits from an abstract generic class如何确定对象是否继承自抽象泛型类
【发布时间】:2013-08-07 08:44:58
【问题描述】:

我有一个从中派生的通用抽象类:

abstract class SuperClass<T>
where T : SuperDataClass

abstract class SuperDataClass

数据类型仅限于 SuperDataClass,因此每个具体的数据类型都必须继承自 SuperDataClass。 最后我有一对 SuperClass 和 SuperDataClass 继承者,例如:

class DataClassA : SuperDataClass
class ClassA : SuperClass<DataClassA>

class DataClassB : SuperDataClass
class ClassB : SuperClass<DataClassB>

我如何检查一个对象,例如ClassA 继承自 SuperClass 却不知道可能的数据类型?

我尝试了以下方法,但不起作用:

if (testObject.GetType().IsAssignableFrom(typeof(SuperClass<SuperDataClass>))) {
    Console.WriteLine("The test object inherits from SuperClass");
}

那么 if 语句应该是什么样子的呢?

【问题讨论】:

  • 我很好奇为什么你想在运行时知道这个。您能否详细说明一下以满足我的好奇心?
  • 我有一个处理多种类型对象的方法。它们都有一个共同的抽象类,在我的示例中 SuperClass 派生自该抽象类。因此,我需要在运行时以相同的方式处理从 SuperClass 派生的所有对象。如果可能,我不想对每种具体类型进行单独处理。

标签: c# generics inheritance types


【解决方案1】:

递归

Type type2 = type; // type is your type, like typeof(ClassA)

while (type2 != null)
{
    if (type2.IsGenericType && 
        type2.GetGenericTypeDefinition() == typeof(SuperClass<>))
    {
        // found
    }

    type2 = type2.BaseType;
}

请注意,如果您正在寻找接口,这将不起作用!

【讨论】:

  • 但是缺少内部类型检查,我理解的操作必须从 SuperDataClass 继承。
  • @Matten 他的问题:ClassA inherits from SuperClass without knowing the possible data type? 其中ClassAClassA : SuperClass&lt;something&gt;
  • type2 本身不是泛型的,它只是从泛型类派生而来,始终使用相同的类型(例如我的示例中的 ClassA)。
  • @sqeez3r 我知道这一点。但它的基本类型是通用的。 “递归”是关键词。
  • @xanatos:对不起,我的课堂上有一些其他答案的代码导致我的测试失败。你的回答很好。非常感谢!
【解决方案2】:

显然所有明显的解决方案(IsSubclassOfIsAssignableFromisas)在这种情况下都不起作用。所以我试着稍微强迫一下,想出了这种方法来测试一个类是否是SuperClass&lt;Something&gt;

private bool IsSuperClassOfSomeKindOfSuperDataClass(Type type)
{
    if (!type.IsGenericType)
        return false;

    var gtd = type.GetGenericTypeDefinition();

    if (gtd != typeof(SuperClass<>))
        return false;

    var genericParameter = type.GetGenericArguments().First();

    return genericParameter.IsSubclassOf(typeof(SuperDataClass));
}

当然,这会测试一个类是否 SuperClass&lt;Something&gt;,而不是它是否继承 SuperClass&lt;Something&gt;,所以接下来显而易见的步骤是编写一个函数为合适的类测试所有继承层次结构:

private bool InheritsFromSuperClassOfSomeKindOfSuperDataClass(Type type)
{
    while (type != typeof(Object))
    {
        if (IsSuperClassOfSomeKindOfSuperDataClass(type))
            return true;

        type = type.BaseType;
    }

    return false;
}

有了这些功能,您正在寻找的测试是:

if (InheritsFromSuperClassOfSomeKindOfSuperDataClass(@object.GetType())) 
    // do stuff...

【讨论】:

  • 这也可以。谢谢!虽然您的解决方案更详细且易于理解,但 xanatos 的解决方案更紧凑。
【解决方案3】:

IsSubclassOf 函数与泛型类型结合使用:

if (@object.GetType().IsGenericType &&
    @object.GetType().GetGenericTypeDefinition().IsSubclassOf(typeof(SuperClass<>))) {
    Console.WriteLine("The object inherits from SuperClass");
}

@object 是您要检查的类型(我从您的问题中复制了命名,但 object 不是好名字,因为它是所有类的超类)。

如果您还想检查泛型类型参数,请使用

if (@object.GetType().IsGenericType &&  
    @object.GetType().GenericTypeArguments[0].IsSubclassOf(typeof(SuperDataClass)) && 
    @object.GetType().IsSubclassOf(typeof(Superclass<>)))

编辑:您的最后一条评论 - 从泛型类型派生的非泛型类型:

if (@object.GetType().IsSubclassOf(typeof(Superclass<>)))

【讨论】:

  • 不幸的是,这不适用于泛型类。如果测试对象(感谢提示,我更改了名称)是 ClassA 类型,则它仅适用于以下语句: if (@object.GetType().IsSubclassOf(typeof(SuperClass))) { Console.WriteLine("测试对象继承自 SuperClass");问题是,我也不事先知道数据类型。
  • 我很确定@JonSkeet 可以根据强制/反强制解释这种行为,但我总是把它们混在一起:)
  • 是否可以使用@[Name of user] 通知尚未参与此主题的人员?对不起,题外话了。
  • @sqeez3r 我认为您需要检查类以及泛型类型参数,更新了我的答案。
  • @Matten:感谢您更新您的答案。测试对象本身不是通用的,它只是从一个通用类派生而来,使用的是相同的类型(例如我的示例中的 ClassA)。
【解决方案4】:

在这里,您应该对预期的类型有所了解。所以在这种情况下,我会使用Type.IsSubclassOf Method

它的一个使用例子是

Class1 myClass = new Class1();
DerivedC1 myDClass = new DerivedC1();
Type myClassType = myClass.GetType();
Type myDClassType = myDClass.GetType();

// Returns true.
bool isSubClass = myDClassType.IsSubclassOf(myClassType));

我希望这会有所帮助。

【讨论】:

  • 可能是因为您的回答原则上与 Matten 相同,而您是第二名。我不知道。您的回答似乎也有效。
  • 这完全是垃圾 - 在我发布之前我不知道上述答案(我已经投票)......
  • 我也不知道为什么。我对 Matten 帖子的评论也应该适用于此。
  • 有趣的是为什么这在您的情况下不起作用。待会儿我会再看一看……
猜你喜欢
  • 2011-03-06
  • 2012-01-10
  • 2023-04-03
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多