如何检查类型是否是子类型或对象的类型?

发布于 2024-08-31 00:42:32 字数 312 浏览 5 评论 0原文

要在 C# 中检查一个类型是否是另一个类型的子类,很简单:

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

但是,这会失败:

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

有没有办法检查一个类型是否是基类本身的子类或基类本身,而不使用 OR 运算符或使用扩展方法?

To check if a type is a subclass of another type in C#, it's easy:

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

However, this will fail:

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

Is there any way to check whether a type is either a subclass OR of the base class itself, without using an OR operator or using an extension method?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

通知家属抬走 2024-09-07 00:42:32

显然,没有。

以下是选项:

Type.IsSubclassOf

正如您已经发现的,如果两种类型相同,这将不起作用,这是一个示例 LINQPad 程序演示:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

输出:

True
False

这表明 DerivedBase 的子类,但 Base 是(显然)不是其自身的子类。

Type.IsAssignableFrom

现在,这将回答您的特定问题,但它也会给您误报。正如 Eric Lippert 在评论中指出的那样,虽然该方法确实会针对上述两个问题返回 True,但它也会针对这些问题返回 True,而您可能不会这样做。 t想要:

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

在这里你得到以下输出:

True
True
True

最后一个True将表明,如果该方法only回答了所提出的问题,则uint[] 继承自 int[] 或者它们是相同的类型,但显然情况并非如此。

所以 IsAssignableFrom 也不完全正确。

isas

在您的问题上下文中 isas 的“问题”是它们需要您可以对对象进行操作并直接在代码中编写其中一种类型,而不是使用 Type 对象。

换句话说,这不会编译:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

这个也不会:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

这个也不会:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

结论

虽然上述方法可能满足您的需求,但您的问题的唯一正确答案(据我所知)是您需要额外的检查:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

这当然在方法中更有意义:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

Apparently, no.

Here's the options:

Type.IsSubclassOf

As you've already found out, this will not work if the two types are the same, here's a sample LINQPad program that demonstrates:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

Output:

True
False

Which indicates that Derived is a subclass of Base, but that Baseis (obviously) not a subclass of itself.

Type.IsAssignableFrom

Now, this will answer your particular question, but it will also give you false positives. As Eric Lippert has pointed out in the comments, while the method will indeed return True for the two above questions, it will also return True for these, which you probably don't want:

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

Here you get the following output:

True
True
True

The last True there would indicate, if the method only answered the question asked, that uint[] inherits from int[] or that they're the same type, which clearly is not the case.

So IsAssignableFrom is not entirely correct either.

is and as

The "problem" with is and as in the context of your question is that they will require you to operate on the objects and write one of the types directly in code, and not work with Type objects.

In other words, this won't compile:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

nor will this:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

nor will this:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

Conclusion

While the above methods might fit your needs, the only correct answer to your question (as I see it) is that you will need an extra check:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

which of course makes more sense in a method:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}
决绝 2024-09-07 00:42:32
typeof(BaseClass).IsAssignableFrom(unknownType);
typeof(BaseClass).IsAssignableFrom(unknownType);
带上头具痛哭 2024-09-07 00:42:32

您应该尝试使用 Type.IsAssignableFrom 代替。

You should try using Type.IsAssignableFrom instead.

吾家有女初长成 2024-09-07 00:42:32

如果您尝试在 Xamarin Forms PCL 项目中执行此操作,则使用 IsAssignableFrom 的上述解决方案会出现错误:

错误:“Type”不包含“IsAssignableFrom”的定义并且
没有扩展方法“IsAssignableFrom”接受第一个参数
可以找到类型“Type”(您是否缺少 using 指令或
装配参考?)

因为 IsAssignableFrom 需要一个 TypeInfo 对象。
您可以使用 System.Reflection 中的 GetTypeInfo() 方法:

typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())

If you're trying to do it in a Xamarin Forms PCL project, the above solutions using IsAssignableFrom gives an error:

Error: 'Type' does not contain a definition for 'IsAssignableFrom' and
no extension method 'IsAssignableFrom' accepting a first argument of
type 'Type' could be found (are you missing a using directive or an
assembly reference?)

because IsAssignableFrom asks for a TypeInfo object.
You can use the GetTypeInfo() method from System.Reflection:

typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())

七秒鱼° 2024-09-07 00:42:32

我发布这个答案是希望有人与我分享这是否是一个坏主意以及为什么这是一个坏主意。在我的应用程序中,我有一个 Type 属性,我想检查它以确保它是 typeof(A) 或 typeof(B),其中 B 是从 A 派生的任何类。所以我的代码:

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

我觉得我可能是这里有点天真,所以欢迎任何反馈。

I'm posting this answer with the hope of someone sharing with me if and why it would be a bad idea. In my application, I have a property of Type that I want to check to be sure it is typeof(A) or typeof(B), where B is any class derived from A. So my code:

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

I feel like I might be a bit naive here so any feedback would be welcome.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文