Simple code that I expect List<int>
's GenericTypeDefinition to contain a generic interface of ICollection<>
. Yet I can't derive an acceptable type from List<int>
which allows me to compare them properly.
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));
}
}
Output
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
I would have expected that r1
contained a type that was equal to b
.
EDIT
Fixed, Jon Skeet gave me the right insight into what was happening.
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));
}
}
Output
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
No, the generic type definition will refer to ICollection<T>
specifically, where T
is the type parameter for the IList<T>
.
Imagine you had something like:
public class Foo<T1, T2> : IEnumerable<T1>, IComparable<T2>
The generic type definition contains all that information - it "knows" that it's specifically IEnumerable<T1>
and IComparable<T2>
, not IEnumerable<T2>
and IComparable<T1>
for example.
You can fix the check by getting the generic type definition for each of the interfaces implemented by the type:
Console.WriteLine(r1.Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == b));
See more on this question at Stackoverflow