【问题标题】:How to check if class "is" an instance of a type given as a variable in C#?如何检查类“是否”是 C# 中作为变量给出的类型的实例?
【发布时间】:2016-10-28 20:21:50
【问题描述】:

我需要做一些这样的检查:

if(thisInstance is ThatClass || thisInstance is ThatOtherClass)

实际上我不需要做很多这些,所以我可以像上面那样简单地写它,但我仍然更喜欢以更整洁的方式来做这件事,例如。像这样:

Type[] arrayOfClasses = new Type[] { typeof(ThatClass), typeof(ThatOtherClass))}
if(isOfAnyType(thisInstance, arrayOfClasses))

但由于某种原因,我无法让它工作。出于某种原因,即使

的字符串表示
thisInstance.GetType()

typeof(ThatClass)

会是一样的,

thisInstance.GetType().IsInstanceOfType(type)

仍将始终导致错误。

如果有所不同,这是一个 Unity 项目,因此如果为可比较的项目(例如 thisInstance.GetType().GetType())调用另一个 GetType(),结果始终是 System.MonoType,在在这种情况下 IsInstanceOfType 总是返回 true,这当然也没有用。

任何想法为什么比较失败或如何使其工作?还是我应该放弃并在需要的地方简单地使用“thisInstance is ThatClass”?

【问题讨论】:

  • 我不会认为您的原始代码以任何方式“不整洁”。这似乎很简单。当您可以使用语言的运算符时,为什么要使用反射?更好的问题是“我可以重组我的代码,以便不需要“是”检查吗?”
  • 好吧,只有这两个类,它并不是特别不整洁,但它不太容易配置,而且如果有更多的类,我认为它会显得有点不整洁。
  • 当然,但是问题是:为什么你有一个程序,你必须对事物的类型进行大量运行时检查?与其试图掩盖运行时检查产生的任何不雅代码,不如尝试完全消除它们。
  • 我的原因是我想要一个方法来选择是否根据调用它的类的类型(+一些附加条件)来做某事。
  • 干脆不要那样做。将被调用者的行为基于调用者的类型是一种非常糟糕的编程实践。寻找另一种方法来解决您的问题。听起来您可能有一个dispatch 问题:您希望在外星人向人类发射子弹时发生一件事,而在人类向机器人发射激光时发生另一件事,也许吧?这个问题有经过充分研究的解决方案。说出你真正的问题是什么,让我们来解决它。

标签: c# unity3d types superclass


【解决方案1】:

你可以使用这样的东西。该方法检查泛型对象是否属于数组中的任何类型并返回一个布尔值。

    public static bool IsOfAnyType<T>(T obj, Type[] types)
    {
        bool isOfAnyType = false;

        for (int i = 0; i < classes.Length; i++)
        {
            if (types[i].IsAssignableFrom (obj.GetType()))
            {
                isOfAnyType = true;
                break;
            }
        }
         return isOfAnyType;
      }     

【讨论】:

  • 为什么需要泛型?一切都已经从“对象”派生而来。使用泛型似乎有很多不必要的开销。
  • @MattRowland - 我会声称相反。如果你使用object object,就会有隐式装箱和拆箱,而使用泛型时,对象保持类型 T。实际上,我猜无论你是否使用对象,它都会转换为相同的机器代码。
  • 谢谢!不管有没有泛型,IsAssignableFrom 似乎都有效!奇怪的是,我以为我已经测试过了,但我想也许我想错了,并且在错误的地方测试了这两种类型。所以无论如何,问题解决了!
  • @Jeffed IsAssignableFrom 学分应该交给 Scott Chamberlain
【解决方案2】:

你可以使用 isSubclass:

thisInstance.GetType().IsSubclassOf(typeof(ThatClass))

【讨论】:

  • 感谢您的建议。但是,当类的类型完全相同时,这将不起作用。
【解决方案3】:

要获得所需的工作方式,您可以使用以下方法:

public static bool IsOfAnyType(object obj, Type[] types)
{
    return types.Any(type => type.IsInstanceOfType(obj));
}

如果你不能使用 Linq,你可以这样写方法:

public static bool IsOfAnyType(object obj, Type[] types)
{
    foreach (var type in types)
    {
        if (type.IsInstanceOfType(obj))
            return true;
    }
    return false;
}

为了测试这一点,我使用了以下代码:

Type[] typesToCheck = { typeof(ThatClass), typeof(ThatOtherClass) };

ThatClass input1 = new ThatClass();
ThatOtherClass input2 = new ThatOtherClass();

if (IsOfAnyType(input1, typesToCheck))
    Console.WriteLine("Hello world from " + input1.GetType());
if (IsOfAnyType(input2, typesToCheck))
    Console.WriteLine("Hello world from " + input2.GetType());

【讨论】:

  • obj.GetType() == typeis的行为不同,需要使用type.IsAssignableFrom (obj.GetType())
  • @ScottChamberlain 很棒的建议,我将其添加到我的答案中。谢谢!
  • 酷,谢谢! Linq 实现非常紧凑。我之前已经将它用于一些集成的东西,但我真的应该开始在更常见的基础上使用它。在我看来,有点违反直觉的是“IsInstanceOfType”实际上做了什么。我会假设“猫是动物类型的实例”是真的,但“动物是猫类型的实例”是错误的,这就是为什么在我的示例中我在开始的帖子中反之亦然。但显然根据文档,只要“当前类型在继承层次结构中”就是真的,所以你的建议有效!
猜你喜欢
  • 2011-03-26
  • 1970-01-01
  • 2018-11-26
  • 2012-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多