我有两个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));
,其中 公共类历史:IEnumerable 但结果我没有像我预期的那样'0',而是'-1'。我不明白 - 为什么会这样?
答案 0 :(得分:5)
当你写Pages.IndexOf(x => x == Pages.ElementAt(0));
时,由于deferred execution(又是懒惰),你实际上多次运行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));
答案 1 :(得分:1)
你的班级T是否实施了IComparable?如果没有,你的等式检查可能会有缺陷,因为框架不知道T = T的确切时间。你也可以通过重写你的类T上的等于我猜测。