Discussion resulting from this answer has me curious. Which is faster:
someEnumerable.Single(predicate);
or
someEnumerable.Where(predicate).Single();
After all, the first is shorter, more concise, and seems to be purpose-built.
Even ReSharper suggests the former:
I was arguing in the previous post, that they are functionally identical, and should have very similar runtime.
In C#, Single. IsNegativeInfinity(Single) is a Single struct method. This method is used to check whether a specified floating-point value evaluates to negative infinity or not. In some floating point operation, it is possible to obtain a result that is negative infinity.
In LINQ, the Single() method is used to return the single element from the collection, which satisfies the condition. In case, if the Single() method found more than one element in collection or no element in the collection, then it will throw the "InvalidOperationException" error.
FirstOrDefault() Returns the first element of a list with any amount of elements, or a default value if the list is empty.
Nothing answers a question like this like a benchmark:
(Updated)
class Program { const int N = 10000; volatile private static int s_val; static void DoTest(IEnumerable<int> data, int[] selectors) { Stopwatch s; // Using .Single(predicate) s = Stopwatch.StartNew(); foreach (var t in selectors) { s_val = data.Single(x => x == t); } s.Stop(); Console.WriteLine(" {0} calls to Single(predicate) took {1} ms.", selectors.Length, s.ElapsedMilliseconds); // Using .Where(predicate).Single() s = Stopwatch.StartNew(); foreach (int t in selectors) { s_val = data.Where(x => x == t).Single(); } s.Stop(); Console.WriteLine(" {0} calls to Where(predicate).Single() took {1} ms.", selectors.Length, s.ElapsedMilliseconds); } public static void Main(string[] args) { var R = new Random(); var selectors = Enumerable.Range(0, N).Select(_ => R.Next(0, N)).ToArray(); Console.WriteLine("Using IEnumerable<int> (Enumerable.Range())"); DoTest(Enumerable.Range(0, 10 * N), selectors); Console.WriteLine("Using int[]"); DoTest(Enumerable.Range(0, 10*N).ToArray(), selectors); Console.WriteLine("Using List<int>"); DoTest(Enumerable.Range(0, 10 * N).ToList(), selectors); Console.ReadKey(); } }
Somewhat shockingly, .Where(predicate).Single()
wins by a factor of about two. I even ran both cases twice to make sure caching, etc. was not a factor.
1) 10000 calls to Single(predicate) took 7938 ms. 1) 10000 calls to Where(predicate).Single() took 3795 ms. 2) 10000 calls to Single(predicate) took 8132 ms. 2) 10000 calls to Where(predicate).Single() took 4318 ms.
Updated Results:
Using IEnumerable<int> (Enumerable.Range()) 10000 calls to Single(predicate) took 7838 ms. 10000 calls to Where(predicate).Single() took 8104 ms. Using int[] 10000 calls to Single(predicate) took 8859 ms. 10000 calls to Where(predicate).Single() took 2970 ms. Using List<int> 10000 calls to Single(predicate) took 9523 ms. 10000 calls to Where(predicate).Single() took 3781 ms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With