【问题标题】:Comparing GenericTypeDefinition of interfaces比较接口的 GenericTypeDefinition
【发布时间】:2015-03-03 09:54:51
【问题描述】:

我期望List<int> 的GenericTypeDefinition 包含ICollection<> 的通用接口的简单代码。然而,我无法从 List<int> 导出可接受的类型,这让我可以正确比较它们。

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    public static void Main()
    {
        var a = typeof(List<int>);
        var b = typeof(ICollection<>);

        var r1 = a.GetGenericTypeDefinition().GetInterfaces();
        foreach (var x in r1)
        {
            Console.WriteLine(x);
        }
        Console.WriteLine();
        Console.WriteLine(b);
        Console.WriteLine();
        Console.WriteLine(r1.Any(x => x == b));
    }
}

输出

System.Collections.Generic.IEnumerable`1[T]
System.Collections.Generic.IReadOnlyList`1[T]
System.Collections.Generic.IReadOnlyCollection`1[T]
System.Collections.IEnumerable
System.Collections.Generic.IList`1[T]
System.Collections.Generic.ICollection`1[T]
System.Collections.ICollection
System.Collections.IList

System.Collections.Generic.ICollection`1[T]

False

我原以为r1 包含一个等于b 的类型。

编辑

已修复,Jon Skeet 让我对正在发生的事情有了正确的了解。

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    public static void Main()
    {
        var a = typeof(List<int>);
        var b = typeof(ICollection<>);

        var r1 = a.GetInterfaces()
            .Where(x => x.IsGenericType)
            .Select(x => x.GetGenericTypeDefinition());

        foreach (var x in r1)
        {
            Console.WriteLine(x);
        }

        Console.WriteLine();
        Console.WriteLine(b);
        Console.WriteLine();
        Console.WriteLine(r1.Contains(b));


    }
}

输出

System.Collections.Generic.IEnumerable`1[T]
System.Collections.Generic.IReadOnlyList`1[T]
System.Collections.Generic.IReadOnlyCollection`1[T]
System.Collections.Generic.ICollection`1[T]
System.Collections.Generic.IList`1[T]

System.Collections.Generic.ICollection`1[T]

True

【问题讨论】:

    标签: c# generics types


    【解决方案1】:

    不,泛型类型定义将具体引用ICollection&lt;T&gt;,其中TIList&lt;T&gt; 的类型参数。

    想象一下你有类似的东西:

    public class Foo<T1, T2> : IEnumerable<T1>, IComparable<T2>
    

    泛型类型定义包含所有这些信息 - 它“知道”它具体是 IEnumerable&lt;T1&gt;IComparable&lt;T2&gt;,而不是 IEnumerable&lt;T2&gt;IComparable&lt;T1&gt;

    您可以通过获取该类型实现的每个接口的泛型类型定义来修复检查:

    Console.WriteLine(r1.Any(x => x.IsGenericType && 
                                  x.GetGenericTypeDefinition()  == b));
    

    【讨论】:

    • 谢谢你,你给了我我需要的洞察力。
    【解决方案2】:

    试试下面这行..

     Console.WriteLine(r1.Any(x => x.Name == b.Name));
    

    代替

    Console.WriteLine(r1.Any(x => x == b));
    

    【讨论】:

    • 不是最安全的类型比较。
    • 正如 Jon 刚刚指出的那样,名称字符串中的 T 标识符不一定与其他名称字符串中的 T 相同。
    • T 不能相同,这就是为什么它是“T”,但是您正在检查接口定义对吗?类型名称不会从 ICollection 更改为任何其他名称。我同意@jon 所说的话。我希望您能通过示例了解“不是最安全的类型比较”评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多