7

I came up with this solution :

if (Take(2).Count() == 1)

is there any more performance solution (or better syntactical sugar) to do this check ? I want a performance way because this will be an extension used on Linq To Entites and Linq to Objects.

I'm not using SingleOrDefault because that will throw and exception if it has more than 1 element.

Based on @Telastyn answer I came up with the following:

public static bool HasOne<T>(this IEnumerable<T> enumerable) {
    var enumerator = enumerable.GetEnumerator();
    return enumerator.MoveNext() && !enumerator.MoveNext();
}

another implementation (slighly slower but 100% sure will work effectivly on Linq to Entities) would be :

public static bool HasOne<T>(this IEnumerable<T> enumerable) {
    return !enumerable.FirstOrDefault().Equals(default(T)) && !enumerable.Skip(1).Any();
}

I'm not sure if the MoveNext one works with IQueryable on Linq to Entites. (any takers? I don't know how to test that)

After some test, Take(2).Count() == 1; is the fastest. :S

18
  • But why do you think that a simple .Count() is not "performant"?
    – JK01
    Aug 15, 2014 at 1:21
  • Wouldn't the performance depend on the specific type of collection and its implementation?
    – user22815
    Aug 15, 2014 at 1:26
  • @JK01 I didn't know but run some test and with 40,000 elements, with count it takes 00.0004618 while with the solution with MoveNext only takes 00.0000067. With 2 elemnts 3169 vs 0011 and with 1 elements it's the same. As bigger the collection, count gets slower. Aug 15, 2014 at 1:31
  • And how many elements do you have? Both of those times effectively the same to a human - instant. You are not going to get support tickets complaining about slow speed either way.
    – JK01
    Aug 15, 2014 at 1:35
  • @Snowman I'm pretty sure that MoveNext() it's optimized for all collections. Any particular collection you think I should test for Count vs MoveNext ? Aug 15, 2014 at 1:36

1 Answer 1

6

Yes, making your own extension that returns false on the second successful MoveNext (or none) should be the most performant implementation for IEnumerable. Anything with a Count property should just check if it is equal to one.

6
  • makes lot of sense. Can you provide me a naive example ? Not familiar with yield. Aug 15, 2014 at 0:25
  • @bart - sorry, my first draft included the yield comment which isn't appropriate in this case. It's just going to use MoveNext three times.
    – Telastyn
    Aug 15, 2014 at 0:27
  • @bart - and .Skip(1).Any() I think should produce he right results and be speedy too.
    – Telastyn
    Aug 15, 2014 at 0:44
  • 1
    .Skip(1).Any() will not work because it will return true when collection have 2+ elements and false on 1 or 0 elements. Aug 15, 2014 at 1:10
  • 1
    Skip 1 not any wont work either. False on 2+ and True on 0 and 1. Aug 15, 2014 at 1:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.