Я наткнулся на эту реализацию в Enumerable.cs с помощью отражателя.
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 value
}
Я думаю, что они должны сломать цикл, если есть более двух элементов, удовлетворяющих условию, почему они всегда проходят через всю коллекцию? В случае, если рефлектор неправильно разбирает 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);
В этом случае я думаю, что он напечатает "получение 0, получение 1", а затем выбросит исключение. Но правда в том, что он "получает 0... получает 10" и выдает исключение. Есть ли алгоритмическая причина, по которой они реализуют этот метод?
РЕДАКТИРОВАТЬ. Некоторые из вас считали это из-за побочных эффектов предикатного выражения, после глубокой мысли и некоторых тестовых случаев, у меня есть вывод, что побочные эффекты не имеют значения в этом случай. Просьба привести пример, если вы не согласны с этим заключением.