Сравнение содержимого массивов, разность SequenceEqual и StructuralComparisons.StructuralEqualityComparer

у меня есть 2 массива :

        int[] arr1 = new int[] { 1, 2, 3 };
        int[] arr2 = new int[] { 1, 2, 3 };

мне нужно проверить, равны ли они (не по ref)

в чем разница между написанием :

        Console.WriteLine(arr1.SequenceEqual(arr2)); //true

vs

        IStructuralEquatable eqArray1 = arr1;
        Console.WriteLine(eqArray1.Equals(arr2, StructuralComparisons.StructuralEqualityComparer));  //true

оба возвращает True..

когда я должен использовать каждый ?

5 ответов


реализация SequenceEqual похоже::

using (IEnumerator<TSource> enumerator1 = first.GetEnumerator())
using (IEnumerator<TSource> enumerator2 = second.GetEnumerator())
{
    while (enumerator1.MoveNext())
    {
        if (!enumerator2.MoveNext() || !comparer.Equals(enumerator1.Current, enumerator2.Current))
        {
            return false;
        }
    }

    if (enumerator2.MoveNext())
    {
        return false;
    }
}

return true;

по умолчанию SequenceEqual способ использовать по умолчанию EqualityComparer<int>.Default на int что такое равенство значений.

Array реализовать IStructuralEquatable С Equal способ:

bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
    if (other == null) return false;

    if (!object.ReferenceEquals(this, other))
    {
        Array array = other as Array;
        if ((array == null) || (array.Length != this.Length))
        {
            return false;
        }
        for (int i = 0; i < array.Length; i++)
        {
            object x = this.GetValue(i);
            object y = array.GetValue(i);

            if (!comparer.Equals(x, y))
            {
                return false;
            }
        }
    }

    return true;
}

на IEqualityComparer из входного параметра используется, здесь вы вводите StructruralEqualityComparer но int не реализует IStructruralEquatable, поэтому он использует компаратор по умолчанию для int что такое равенство значений.

но, само собой ввод StructruralEqualityComparer, потому что int не является структурным, вы должны просто использовать:

(arr1 as IStructuralEquatable).Equals(arr2, EqualityComparer<int>.Default);

он все еще работает. Вы должны использовать StructruralEqualityComparer если элемент в массиве structrural

Итак, чтобы подвести итог, реализация для обоих видов одинакова, оба повторяют два массива на основе равенства значений int чтобы сделать сравнение.

Я бы предпочел LINQ verson, так как он более читаем.


стандартные проверки равенства в .NET использует EqualityComparer.По умолчанию для сравнения. Например словари или метод SequenceEqual вы написали там использует EqualityComparer.По умолчанию по умолчанию. И этот компаратор либо использует метод Equals(object), либо метод Equals (T) при наличии IEquatable реализации интерфейса.

но вы всегда можете дать другие компараторы, такие как StructuralComparisons.StructuralEqualityComparer для словарей или методов, таких как SequenceEqual.

Итак, основное различие между двумя методами-это метод проверки равенства, который они используют. SequenceEqual использует IEquatable метод интерфейса для проверок и StructuralComparisons.StructuralEqualityComparer использует метод интерфейса IStructuralEquatable для проверок. В результате проверки равенства по умолчанию два сравниваемых элемента должны быть одного типа, но StructuralEqualityComparer не требует, чтобы они были одного типа. Как следует из названия, он должен сравнивать содержание.


у меня просто был вопрос и увидел, что этот вопрос не был правильно ответил. Есть разница между структурным и последовательным - первое сравнение глубокое, а второе-нет.

этот простой код демонстрирует и выдает True False:

int[][] ints1 = { new int[] { 3, 4 } };
int[][] ints2 = { new int[] { 3, 4 } };
Console.WriteLine(StructuralComparisons.
                          StructuralEqualityComparer.Equals(ints1, ints2));
Console.WriteLine(ints1.SequenceEqual(ints2));

имя "последовательность" предполагает одномерность, поэтому выбор имени подходит.


аттракцион LINQ версия является наиболее гибким, он может сравнить два enumerables.
В StructuralComparisons.Версия StructuralEqualityComparer требует, чтобы две коллекции могли поддерживать интерфейс IStructuralEquatable. Но я ожидал бы, что позже быстрее, если два списка имеют неравномерную длину.


Я думаю, что система.Linq ваш друг:

bool isEqual = Enumerable.SequenceEqual(array1, array2);