What is the benefit of SequenceEqual?

不羁岁月 提交于 2020-01-03 05:36:28

问题


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 Lists 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 Arrays 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!