坏实施Enumerable.Single的?Enumerable、Single

2023-09-02 23:48:55 作者:寻你的轮廓

我在Enumerable.cs碰到这个实施反射。

I came across this implementation in Enumerable.cs by reflector.

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错误,我写了一个简单的测试:

I think they should break the loop if there are more than 2 items meets the condition, why they always loop through the whole collection? In case of that reflector disassembles the dll incorrectly, I write a simple test:

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);

有关本次测试的情况下,我认为它会打印出越来越0,得到1,然后抛出异常。但事实是,它让渐0 ......让10,并抛出一个异常。 有他们实现这个方法任何这样的算法的原因是什么?

For this test case, I think it will print "getting 0, getting 1" and then throw an exception. But the truth is, it keeps "getting 0... getting 10" and throws an exception. Is there any algorithmic reason they implement this method like this?

修改你们当中有些人认为这是因为的的predicate EX pression副作用的,深刻的思想和一些测试用例后,我有一个结论,即的副作用并不在这种情况下没关系。请提供一个例子,如果你不同意这个结论。

EDIT Some of you thought it's because of side effects of the predicate expression, after a deep thought and some test cases, I have a conclusion that side effects doesn't matter in this case. Please provide an example if you disagree with this conclusion.

推荐答案

是的,我也觉得有点奇怪尤其是因为这并不需要predicate过载(即适用于刚刚序列)的确实的似乎有快速掷优化。

Yes, I do find it slightly strange especially because the overload that doesn't take a predicate (i.e. works on just the sequence) does seem to have the quick-throw 'optimization'.

然而,在首创置业的防守,我会说,在 InvalidOperation异常的单抛出一个的