public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
//check parameters
TSource local = default(TSource);
long num = 0L;
foreach (TSource local2 in source)
{
if (predicate(local2))
{
local = local2;
num += 1L;
//I think they should do something here like:
//if (num >= 2L) throw Error.MoreThanOneMatch();
//no necessary to continue
}
}
//return different results by num's value
}
我认为如果有超过2个项目符合条件,他们应该打破循环,为什么他们总是遍历整个集合?以防反射器错误地拆解dll,我写了一个简单的测试:
class DataItem
{
private int _num;
public DataItem(int num)
{
_num = num;
}
public int Num
{
get{ Console.WriteLine("getting "+_num); return _num;}
}
}
var source = Enumerable.Range(1,10).Select( x => new DataItem(x));
var result = source.Single(x => x.Num < 5);
对于这个测试用例,我认为它会打印"getting 0, getting 1"然后抛出一个异常。但事实是,它保持着"getting 0... getting 10"并抛出了一个异常。 他们为什么要以这种方式实现这个方法,是否有算法上的原因?
编辑:有些人认为这是由于谓词表达式的副作用,经过深思熟虑和一些测试用例,我得出结论,在这种情况下副作用并不重要。如果你不同意这个结论,请提供一个例子。
12年后,现在是2023年,我发现最新的.NET已经将实现方式改正了 :) https://github.com/dotnet/runtime/blob/main/src/libraries/System.Linq/src/System/Linq/Single.cs