定义System.Linq.ILookUp<TKey, TElement>
阅读
interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable
{
int Count { get; }
IEnumerable<TElement> this[TKey key] { get; }
bool Contains(TKey key);
}
自 IEnumerable
在 IGrouping<TKey, TElement>
中是协变的, IGrouping<TKey, TElement>
在 TElement
中是协变的并且界面只暴露TElement
作为返回类型,我假设 ILookup
在 TElement
中也是协变的.的确,定义
interface IMyLookup<TKey, out TElement> : IEnumerable<IGrouping<TKey, TElement>>, IEnumerable
{
int Count { get; }
IEnumerable<TElement> this[TKey key] { get; }
bool Contains(TKey key);
}
编译没有问题。
那么,原始定义中缺少 out 关键字的原因可能是什么?可能会在 Linq 的 future 版本中添加它吗?
最佳答案
跟踪 MSDN 文档,Covariance and Contravariance in Generics在.NET Framework 4 之前已经引入了IEnumerable<T>
从 .NET Framework 2.0 到 .NET Framework 3.5。然后在.NET Framework 4.0中我们可以看到IEnumerable<out T>
带有类型参数 T
作为协方差。
IGrouping<TKey, TElement>
和 ILookup<TKey, TElement>
自 .NET Framework 3.5 以来就已经存在。在 .NET Framework 4.0 中,前者已更新为 IGrouping<out TKey, out TElement>
但后者在没有说明原因的情况下被省略了。
TKey
自 Contains(TKey)
的实现以来不能是协变的 |和 this[TKey]
防止这种情况发生。
关于TElement
这个问题还不清楚。我不相信设计师只是错过了它。也许原因在于对 future 的计划。或者他们想阻止类似下面的事情,但我不知道为什么:
string[] strings = new[] {"a", "a", "b", "b", "b", "c"};
ILookup<string, string> lookup = strings.ToLookup(s => s); // Valid.
ILookup<string, object> lookup = strings.ToLookup(s => s); // Now invalid, but would correct if TElement was covariant (out TElement).
还有其他作者,关注这个问题:
ToLookup :
One slightly odd point to note is that while IGrouping is covariant in TKey and TElement, ILookup is invariant in both of its type parameters. While TKey has to be invariant, it would be reasonable for TElement to be covariant
关于c# - ILookup<TKey, TElement> 不应该在 TElement 中(声明)协变吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14883727/