IEnumerable泛型的扩展

本文关键字:扩展 泛型 IEnumerable | 更新日期: 2023-09-27 18:15:30

IEnumerable有两个扩展:

public static class IEnumerableGenericExtensions
{
    public static IEnumerable<IEnumerable<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
    {
        List<T> toReturn = new List<T>(max);
        foreach (var item in source)
        {
            toReturn.Add(item);
            if (toReturn.Count == max)
            {
                yield return toReturn;
                toReturn = new List<T>(max);
            }
        }
        if (toReturn.Any())
        {
            yield return toReturn;
        }
    }
    public static int IndexOf<T>(this IEnumerable<T> source, Predicate<T> searchPredicate)
    {
        int i = 0;
        foreach (var item in source)
            if (searchPredicate(item))
                return i;
            else
                i++;
        return -1;
    }
}

然后我写这段代码:

        Pages = history.InSetsOf<Message>(500);
        var index = Pages.IndexOf(x => x == Pages.ElementAt(0));

,public类History: IEnumerable但结果我得到的不是我预期的" 0 "而是" -1 "我不明白——为什么?

IEnumerable泛型的扩展

当你写Pages.IndexOf(x => x == Pages.ElementAt(0));时,你实际上运行InSetsOf 很多次,由于延迟执行(又名懒惰)。扩大:

  • Pages = history.InSetsOf<Message>(500) -这行根本不运行InSetsOf
  • Pages.IndexOf -在Pages上迭代,所以它开始执行InSetsOf一次。
  • x == Pages.ElementAt(0) -再次执行InSetsOf,对Pages集合中的每个元素执行一次(或者至少直到searchPredicate返回true,这在这里不会发生)。

每次运行InSetsOf时,您都会创建一个新列表(具体来说,是一个新的第一个列表,因为您使用ElementAt(0))。这是两个不同的对象,因此==在它们之间的比较失败。

一个非常简单的修复方法是返回一个列表,这样Pages就不是一个延迟的查询,而是一个具体的集合:
Pages = history.InSetsOf<Message>(500).ToList();

另一种选择是使用SequenceEqual,尽管我建议缓存第一个元素:

Pages = history.InSetsOf<Message>(500);
var firstPage = Pages.FirstOrDefault();
var index = Pages.IndexOf(x => x.SequenceEqual(firstPage));

你的类T实现了IComparable吗?如果不是,你的相等性检查可能是有缺陷的,因为框架不知道T= T的确切时间。我猜你也可以通过在你的类T上重写等号来获得。