【问题标题】:Why is checking equality of open generic types inconsistent? [duplicate]为什么检查开放泛型类型的相等性不一致? [复制]
【发布时间】:2021-01-14 19:31:37
【问题描述】:

出于某种原因:

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

false 但是这个:

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

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

在第一个示例中,接口数组中的[0]IDictionary'2,如果我直接将它与typeof(没有.Contains(...))与==.Equals(...) 甚至.IsAssignableFrom(...) 进行比较结果是一样的。

请有人告诉我为什么!

【问题讨论】:

  • 我没有在开放式上使用它。
  • 链接的问题是关于接口的,但是类的点是一样的。
  • 我不明白,我没有投票关闭提到的重复,但另一个我不记得了,在我看来......

标签: c# generics reflection


【解决方案1】:

因为从.GetGenericTypeDefinition().GetInterfaces() 返回的接口不是“泛型类型定义”(它们的IsGenericTypeDefinitionfalse),所以它们不能严格等于IDictionary&lt;,&gt;(即泛型类型定义, 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&lt;,&gt;,因为它是IDictionary&lt;TKey2, TValue2&gt;

【讨论】:

  • 我现在看到,由于某种原因,类型参数是 TKeyTValue 不是实际类型,所以它就像一个伪构造类型。感谢您指出这一点。
  • 实际上这些是两者的类型参数。我想知道为什么一个说它是开放的,而另一个没有?
  • @Nintynuts 他们只有同名...我准备一个例子
  • @Nintynuts 见dotnetfiddle.net/ym2kUq
猜你喜欢
  • 1970-01-01
  • 2021-10-13
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
  • 2020-02-18
相关资源
最近更新 更多