比较两个System.Type是否相等失败了?

3

我已经编写了这个扩展方法来检查一个类型是否实现了一个接口。为了使它能够正确地工作,它需要比较两个类型。然而,这种比较似乎并不可靠:

public static bool ImplementsInterface(this Type type, Type testInterface)
{
    if (testInterface.GenericTypeArguments.Length > 0)
    {
        return testInterface.IsAssignableFrom(type);
    }
    else
    {
        foreach (var @interface in type.GetInterfaces())
        {
            // This doesn't always work:
            if (@interface == testInterface)
            // But comparing the names instead always works!
            // if (@interface.Name == testInterface.Name)
            {
                return true;
            }
        }
        return false;
    }
}

这是我的比较失败的情况:
public static class TestInterfaceExtensions
{
    interface I1 { }
    interface I2<T> : I1 { }
    class Class1Int : I2<int> { }

    [Fact]
    public void ImplementsInterface()
    {
        Assert.True(typeof(Class1Int).ImplementsInterface(typeof(I2<>)));
    }
}

正如评论中提到的,如果我比较类型名称,它总是按预期工作。我想知道这里发生了什么。


2
我的意思是,你正在比较一个开放接口和一个封闭接口,所以它们肯定不一样。但是肯定有一种方法可以做到你正在尝试的事情...只需要在调试器中查看即可。 - Jamiec
2
请检查此答案是否适用于您的应用程序。https://dev59.com/B2gv5IYBdhLWcg3wSe0f#10718451 - Diogozx
1
我明白了,所以未绑定的I2<>表达式不应该等于I2<int>。字符串名称比较只是巧合,因为两种情况下名称都是I2`1。感谢回复! - Sora
1个回答

4
如果接口是通用的,您需要将其与通用类型定义进行比较:
public static bool ImplementsInterface(this Type type, Type testInterface)
{
    if (testInterface.GenericTypeArguments.Length > 0)
    {
        return testInterface.IsAssignableFrom(type);
    }
    else
    {
        foreach (var @interface in type.GetInterfaces())
        {
            var compareType = @interface.IsGenericType
                ? @interface.GetGenericTypeDefinition()
                : @interface;
            if (compareType == testInterface)
            {
                return true;
            }
        }
        return false;
    }
}

这对许多测试用例都有效:

Console.WriteLine(typeof(Class1Int).ImplementsInterface(typeof(I2<>)));     // True
Console.WriteLine(typeof(Class1Int).ImplementsInterface(typeof(I2<int>)));  // True
Console.WriteLine(typeof(Class1Int).ImplementsInterface(typeof(I2<bool>))); // False
Console.WriteLine(typeof(Class1Int).ImplementsInterface(typeof(I1)));       // True
Console.WriteLine(typeof(Class1Int).ImplementsInterface(typeof(I3)));       // False

实时演示:https://dotnetfiddle.net/bBslxH


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接