比较接口的 GenericTypeDefinition
Comparing GenericTypeDefinition of interfaces
我希望 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
不,泛型类型定义将具体引用 ICollection<T>
,其中 T
是 IList<T>
.
的类型参数
想象一下你有这样的东西:
public class Foo<T1, T2> : IEnumerable<T1>, IComparable<T2>
泛型类型定义包含所有这些信息 - "knows" 具体是 IEnumerable<T1>
和 IComparable<T2>
,而不是 IEnumerable<T2>
和 IComparable<T1>
。
您可以通过获取类型实现的每个接口的通用类型定义来修复检查:
Console.WriteLine(r1.Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == b));
试试下面的行..
Console.WriteLine(r1.Any(x => x.Name == b.Name));
而不是
Console.WriteLine(r1.Any(x => x == b));
我希望 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
不,泛型类型定义将具体引用 ICollection<T>
,其中 T
是 IList<T>
.
想象一下你有这样的东西:
public class Foo<T1, T2> : IEnumerable<T1>, IComparable<T2>
泛型类型定义包含所有这些信息 - "knows" 具体是 IEnumerable<T1>
和 IComparable<T2>
,而不是 IEnumerable<T2>
和 IComparable<T1>
。
您可以通过获取类型实现的每个接口的通用类型定义来修复检查:
Console.WriteLine(r1.Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == b));
试试下面的行..
Console.WriteLine(r1.Any(x => x.Name == b.Name));
而不是
Console.WriteLine(r1.Any(x => x == b));