C#中的类型相等检查

时间:2012-08-01 14:11:55

标签: c# types equality

使用

public abstract class CompositionPlugin { ... }

public class MyCompositionPlugin : CompositionPlugin { ... }

我想检查一个对象的类型是否等于给定的类型:

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        foreach (CompositionPlugin plugin in CompositionPlugins)
        {
            if (plugin.GetType().Equals(ofType))
                return plugin;
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}

这样调用方法:

Framework framework = new Framework();
// Adding the plugin to the framework is done by loading an assembly and
// checking if it contains plugin-compatible classes (i.e. subclasses
// of <CompositionPlugin>)
framework.RegisterAssembly("E:\\Projects\\Framework\\MyPlugin\\bin\\Debug\\MyPlugin.dll");
CompositionPlugin plugin = framework.GetCompositionPlugin(typeof(MyCompositionPlugin));

然而,在测试时,这个检查总是失败,即使我肯定在我要求的列表中有这种类型的对象。

根据我的理解,它应该返回MyCompositionPlugin - 列表中找到的CompositionPlugins的第一个实例。

我的类型检查错了吗?为什么?它是如何正确完成的?

5 个答案:

答案 0 :(得分:7)

您想在类型上使用IsAssignableFrom

if (ofType.IsAssignableFrom(plugin.GetType())

Equals仅处理类型完全相同的情况。 IsAssignableFrom还处理ofType可能是您的插件继承的类型或实现的接口的情况。

答案 1 :(得分:5)

不是答案,但评论太长了...... 您确定问题不在于如何调用方法或填充集合吗? 比较本身应该没问题,正如您的代码的简化版本所示:

class A {}

bool TestType(A item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

现在:

Console.WriteLine(TestType(new A(), typeof(A))); // True
Console.WriteLine(TestType(new A(), typeof(string))); // False

修改

我认为@vcsjones是对的。您正在尝试将派生类与基类进行比较。 在行foreach (CompositionPlugin plugin in CompositionPlugins)中,您声明插件是CompositionPlugin,但在客户端代码中,您将其与typeof(MyCompositionPlugin)进行比较。 (重新编辑不,我错了,你的案例对应于我的Console.WriteLine中返回true的第4个

在与您类似的场景中查看此示例的Equals真值表:

class CompositionPlugin {}
class MyCompositionPlugin : CompositionPlugin  {}

// Define other methods and classes here
bool TestType(CompositionPlugin item, Type ofType)
{       
    return item.GetType().Equals(ofType);
}

现在

Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(CompositionPlugin))); //True
Console.WriteLine(TestType(new CompositionPlugin(), 
            typeof(MyCompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(), 
            typeof(CompositionPlugin))); //False
Console.WriteLine(TestType(new MyCompositionPlugin(),
            typeof(MyCompositionPlugin))); //True

答案 2 :(得分:3)

使用关键字is

if (plugin is ofType)
    return plugin;

编辑:

我必须和@vcsjones一起去这个。使用isassignablefrom功能。

但是如果你真的认为它应该可以工作,我总是创建快速函数来将调试文本写入文件。

public class Framework {

    public IList<CompositionPlugin> CompositionPlugins = new List<CompositionPlugin>();

    public CompositionPlugin GetCompositionPlugin(Type ofType)
    {
        using(var writer = System.IO.File.CreateText(@"C:\test.log"))
        {
            writer.WriteLine("ofType: " + ofType.toString());
            foreach (CompositionPlugin plugin in CompositionPlugins)
            {
                writer.WriteLine("plugin: " + plugin.GetType().toString());
                if (plugin.GetType().Equals(ofType))
                    return plugin;
            }
        }

        throw new ArgumentException("A composition plugin of type " + ofType.FullName + " could not be found");
    }
}

答案 3 :(得分:0)

事实证明,我最初忽略的信息,认为它并不重要,毕竟是这样。

MyCompositionPluginCompositionPlugin都在不同的程序集中定义,执行程序在运行时动态加载。

.NET-Runtime现在考虑从不同的程序集加载的类型而不是执行程序集引用的类型,使MyCompositionPlugin - Program中的类型被认为不等于{ {1}}从另一个程序集加载,即使它们实际上是相同的。

比较两者的相等性的解决方案(因为它们在常识中是相同的“类”)是将它分解为定义组件的字符串相等,这可以说是脏的,但是诀窍是

MyCompositionPlugin

指向Paolo Falabella

this question致敬

答案 4 :(得分:0)

您的问题很可能是因为程序集第二次加载而且相等失败,最好避免再次加载程序集,因此您可以使用普通类型比较而不是需要使用那个脏字符串比较。我遇到了同样的问题,我的插件接口是在一个单独的程序集中定义的,这个程序集存在于启动文件夹中,但也存在于插件文件夹中,动态加载的插件程序集因此导致接口类型相等失败。我从插件文件夹中删除了界面dll,之后一切都按预期工作。