Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Single() not return directly when more than one element is found? [duplicate]

I found (roughly) this code in the Enumerable.Single method while inspecting it with some decompiler:

foreach (TSource current in source)
{
    if (predicate(current))
    {
        result = current;
        num += 1L;
    }
}

if (num > 1L)
{
     throw Error.MoreThanOneMatch();
}

As you can see, it loops over all items before throwing. Why doesn't it break when num > 1?

like image 502
Vince Avatar asked Jul 19 '13 09:07

Vince


1 Answers

Agree, that it will be better from terms of performance (EDIT: if we are expecting more than one item matching our predicate, which we should not do):

foreach (TSource current in source)
{
    if (predicate(current))
    {
        result = current;
        num += 1L;

        if (num > 1L)
            throw Error.MoreThanOneMatch();
    }
}

if (num == 0L)
   throw Error.NoMatch();

return local;

Looks like they decided to make results analyzing more clear and separated it from enumerating source. But then I wonder why simple switch was not used:

switch((int)num)
{
   case 0: throw Error.NoMatch();
   case 1: return local;
   default:
       throw Error.MoreThanOneMatch();    
}

Regarding to performance issues - I think it's assumed that Single should be called when you are really expecting single result. Zero or more results is an exceptional path, which should not occur often (as any exception). So, it's more your program's logic error if source contain many items matching predicate.

like image 115
Sergey Berezovskiy Avatar answered Oct 16 '22 03:10

Sergey Berezovskiy