问题
I did a comparison between SequenceEqual and element comparison in for loop.
static void Main(string[] args)
{
//var myList = new List<short>();
//var anotherList = new List<short>();
var myList = new short[2000000];
var anotherList = new short[2000000];
for (int i = 0; i < 2000000; i++)
{
//myList.Add(5);
//anotherList.Add(5);
myList[i] = 5;
anotherList[i] = 5;
}
var watch = System.Diagnostics.Stopwatch.StartNew();
//for (int i = 0; i < 2000000; i++)
//{
// if (myList[i] != anotherList[i])
// break;
//}
bool isEqual = myList.SequenceEqual(anotherList);
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine(elapsedMs);
Console.Read();
}
In the case when myList and anotherList are arrays, the direct comparison executes for 4 ms, SequenceEqual executes for 21ms. When myList and anotherList are lists, the direct comparison executes for 13 ms, SequenceEqual for 30 ms.
If it is so much slower, are there cases when it would be beneficial to use? I can only think of one, that it saves several lines of code.
回答1:
Looking into especially List
s more specifically, it seems a lot of slow down comes from the generic implementation in SequenceEqual
using the generic IEnumerator
instead of the List
specific version, which is more than twice as fast. However, if you are going to test for List
anyway, might as well code in the for
loop directly instead of using enumeration.
Note that testing for IList
is a lot slower, because List
doesn't implement IList<T>.operator[]
which means it calls IList.operator[]
which returns object
and causes boxing.
I also special case Array
s as the IList
interface is much slower than direct access, again due to boxing.
Of course, taking advantage of the high speed Count
or Length
available for known types makes unequal length comparisons tremendously faster than SequenceEqual
. OTOH, if the first two elements are unequal, SequenceEqual
can be faster than my function.
Here is my LocalSequenceEqual
:
public static bool LocalSequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer = null) {
if (first is ICollection<TSource> fc && second is ICollection<TSource> sc)
if (fc.Count != sc.Count)
return false;
var cmp = comparer ?? EqualityComparer<TSource>.Default;
if (first is TSource[] fa && second is TSource[] sa) {
for (int j1 = 0; j1 < fa.Length; ++j1)
if (!cmp.Equals(fa[j1], sa[j1]))
return false;
return true;
}
if (first is List<TSource> fl && second is List<TSource> sl) {
for (int j1 = 0; j1 < fl.Count; ++j1) {
if (!cmp.Equals(fl[j1], sl[j1]))
return false;
}
return true;
}
using (var e1 = first.GetEnumerator()) {
using (var e2 = second.GetEnumerator()) {
while (e1.MoveNext()) {
if (!(e2.MoveNext() && cmp.Equals(e1.Current, e2.Current)))
return false;
}
if (e2.MoveNext())
return false;
}
}
return true;
}
来源:https://stackoverflow.com/questions/49581893/what-is-the-benefit-of-sequenceequal