为什么检查开放泛型类型的相等性不一致?

Why is checking equality of open generic types inconsistent?

出于某种原因:

typeof(Dictionary<string,string>).GetGenericTypeDefinition()
                                 .GetInterfaces()
                                 .Contains(typeof(IDictionary<,>))

false但是这个:

typeof(Dictionary<string,string>).GetInterfaces()
                                 .Any(i => i.IsGenericType
                                        && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))

true,即使它们在具有相同 GUID 的调试器中显示为 IDictionary'2

在第一个示例中,接口数组中的 [0]IDictionary'2,如果我直接将其与 typeof(没有 .Contains(...))或 ==.Equals(...) 甚至 .IsAssignableFrom(...) 都是相同的结果。

拜托,有人告诉我为什么!

因为从.GetGenericTypeDefinition().GetInterfaces()返回的接口不是“通用类型定义”(它们的IsGenericTypeDefinitionfalse),所以它们不能严格等于IDictionary<,>(这是一个泛型类型定义,IsGenericTypeDefinitiontrue)。

第二块代码从接口钻取到它们的通用类型定义,让您进行比较。

关于所发生情况的一个简单示例:

class MyDictionary<TKey2, TValue2> : IDictionary<TKey2, TValue2>
{
    public TValue2 this[TKey2 key] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    public ICollection<TKey2> Keys => throw new NotImplementedException();
    public ICollection<TValue2> Values => throw new NotImplementedException();
    public int Count => throw new NotImplementedException();
    public bool IsReadOnly => throw new NotImplementedException();
    public void Add(TKey2 key, TValue2 value) => throw new NotImplementedException();
    public void Add(KeyValuePair<TKey2, TValue2> item) => throw new NotImplementedException();
    public void Clear() => throw new NotImplementedException();
    public bool Contains(KeyValuePair<TKey2, TValue2> item) => throw new NotImplementedException();
    public bool ContainsKey(TKey2 key) => throw new NotImplementedException();
    public void CopyTo(KeyValuePair<TKey2, TValue2>[] array, int arrayIndex) => throw new NotImplementedException();
    public IEnumerator<KeyValuePair<TKey2, TValue2>> GetEnumerator() => throw new NotImplementedException();
    public bool Remove(TKey2 key) => throw new NotImplementedException();
    public bool Remove(KeyValuePair<TKey2, TValue2> item) => throw new NotImplementedException();
    public bool TryGetValue(TKey2 key, out TValue2 value) => throw new NotImplementedException();
    IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
}

然后:

var interfaces = typeof(MyDictionary<string, string>).GetGenericTypeDefinition().GetInterfaces();
var idict1 = interfaces[0];
var idict2 = idict1.GetGenericTypeDefinition();

Console.WriteLine(idict1);
Console.WriteLine(idict2);

结果:

System.Collections.Generic.IDictionary`2[TKey2,TValue2] <-- This is what you get with GetInterfaces()
System.Collections.Generic.IDictionary`2[TKey,TValue]   <-- And this is the generic type definition

很明显 idict1 不可能是 IDictionary<,>,因为它是 IDictionary<TKey2, TValue2>