Created
December 9, 2011 10:49
-
-
Save ThatRendle/1451071 to your computer and use it in GitHub Desktop.
Single-element enumerable comparison
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace EnumerableOfOneTest | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Collections; | |
using System.Diagnostics; | |
class Program | |
{ | |
static void Main() | |
{ | |
int n = 0; | |
var watch = Stopwatch.StartNew(); | |
for (int i = 0; i < 10000000; i++) | |
{ | |
n += GetOneCustomClass().Single(); | |
} | |
watch.Stop(); | |
Console.WriteLine("Custom class: {0} ({1:##,#})", watch.Elapsed, n); | |
n = 0; | |
watch = Stopwatch.StartNew(); | |
for (int i = 0; i < 10000000; i++) | |
{ | |
n += GetOneIterator().Single(); | |
} | |
watch.Stop(); | |
Console.WriteLine("Iterator : {0} ({1:##,#})", watch.Elapsed, n); | |
n = 0; | |
watch = Stopwatch.StartNew(); | |
for (int i = 0; i < 10000000; i++) | |
{ | |
n += GetOneArray().Single(); | |
} | |
watch.Stop(); | |
Console.WriteLine("Array : {0} ({1:##,#})", watch.Elapsed, n); | |
} | |
private static IEnumerable<int> GetOneCustomClass() | |
{ | |
return new SingleEnumerable<int>(1); | |
} | |
private static IEnumerable<int> GetOneArray() | |
{ | |
return new[] {1}; | |
} | |
private static IEnumerable<int> GetOneIterator() | |
{ | |
yield return 1; | |
} | |
} | |
class SingleEnumerable<T> : IEnumerable<T> | |
{ | |
private readonly T _value; | |
public SingleEnumerable(T value) | |
{ | |
_value = value; | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return new SingleEnumerator(_value); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
class SingleEnumerator : IEnumerator<T> | |
{ | |
private readonly T _value; | |
private int _state; | |
public SingleEnumerator(T value) | |
{ | |
_value = value; | |
} | |
public void Dispose() | |
{ | |
} | |
public bool MoveNext() | |
{ | |
// Can only do this once (NB: post-fix ++ returns previous value of _state) | |
return _state++ == 0; | |
} | |
public void Reset() | |
{ | |
_state = 0; | |
} | |
public T Current | |
{ | |
get | |
{ | |
// Only valid after a single MoveNext call() | |
if (_state != 1) throw new InvalidOperationException(); | |
return _value; | |
} | |
} | |
object IEnumerator.Current | |
{ | |
get { return Current; } | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Timings on my laptop:
Custom class: 00:00:00.4003948 (10,000,000)
Iterator : 00:00:00.5607078 (10,000,000)
Array : 00:00:02.1428748 (10,000,000)