6

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

  • But why do you think that a simple .Count() is not "performant"? – JK01 Aug 15 '14 at 1:21
  • Wouldn't the performance depend on the specific type of collection and its implementation? – user22815 Aug 15 '14 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. – Bart Calixto Aug 15 '14 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 '14 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 ? – Bart Calixto Aug 15 '14 at 1:36
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.

|improve this answer|||||
  • makes lot of sense. Can you provide me a naive example ? Not familiar with yield. – Bart Calixto Aug 15 '14 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 '14 at 0:27
  • @bart - and .Skip(1).Any() I think should produce he right results and be speedy too. – Telastyn Aug 15 '14 at 0:44
  • .Skip(1).Any() will not work because it will return true when collection have 2+ elements and false on 1 or 0 elements. – Bart Calixto Aug 15 '14 at 1:10
  • 1
    Skip 1 not any wont work either. False on 2+ and True on 0 and 1. – Bart Calixto Aug 15 '14 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.