IGrouping支持ElementAt方法以索引分组的集合。那么,为什么方括号运算符不起作用?

我可以做类似的事情

 list.GroupBy(expr).Select(group => group.ElementAt(0)....)


但不是

 list.GroupBy(expr).Select(group => group[0]....)


我猜这是因为IGrouping接口不会使方括号运算符过载。 IGrouping没有重载方括号运算符来执行与ElementAt相同的操作,这是否有充分的理由?

最佳答案

这有点从头到尾,所有可枚举都受(而不是支持,因为它是从外部提供的扩展方法)ElementAt(),但是只有某些类型也支持[],例如List<T>或任何实现IList<T>的东西。

Grouping当然可以很容易地实现[],但是随后必须始终这样做,因为API是一个承诺,它必须继续保持下去,否则它将破坏按旧方法编写的代码打破它。

ElementAt()采用一种测试和使用的方法,如果某些东西支持IList<T>,它将使用[],否则它将计算适当的数字。由于您可以对任何序列进行计数,因此它可以支持任何枚举。

碰巧Grouping确实支持IList<T>但作为显式接口,因此以下工作:

//Bad code for demonstration purpose, do not use:
((IList<int>)Enumerable.Range(0, 50).GroupBy(i => i / 5).First())[3]


但是因为很明显,如果在另一种方法中发现了优势,则不必继续支持它。

ElementAt的测试和使用方法:

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)
{
    if (source == null) throw Error.ArgumentNull("source");
    IList<TSource> list = source as IList<TSource>;
    if (list != null) return list[index];
    if (index < 0) throw Error.ArgumentOutOfRange("index");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        while (true)
        {
            if (!e.MoveNext()) throw Error.ArgumentOutOfRange("index");
            if (index == 0) return e.Current;
            index--;
        }
    }
}


因此,可以从中获得最佳O(1)行为,而不是其他形式的O(n)行为,但同时又不限制Grouping做出设计者可能会后悔的承诺。

关于c# - IGrouping ElementAt与方括号运算符,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33374600/

10-12 15:27