比较数组内容,SequenceEqual 和 StructuralComparisons.StructuralEqualityComparer 的区别

问题描述 投票:0回答:6

我有 2 个数组:

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

我需要检查它们是否相等(不是通过引用)

写作有什么区别:

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

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

两者都返回 True..

我应该什么时候使用每一个?

c# .net .net-4.0
6个回答
2
投票

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);

它仍然有效。如果数组中的项目是

structrural
,则应使用 StructruralEqualityComparer

综上所述,两者的实现是相同的,都是基于

int
的值相等来迭代两个数组来进行比较。

我更喜欢 LINQ 版本,因为它更具可读性。


2
投票

我刚刚有一个相关的问题,发现这个问题实际上从未得到正确的回答。结构和顺序之间存在差异 - 第一个比较是深入的,而第二个则不是。

这个简单的代码演示并产生

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));

名称“序列”暗示一维主义,因此名称选择是合适的。


1
投票

.NET 中的标准相等性检查使用 EqualityComparer.Default 进行比较。例如,您在那里编写的字典或 SequenceEqual 方法默认使用 EqualityComparer.Default。并且该比较器在存在 IEquatable 接口实现的情况下使用 Equals(object) 方法或 Equals(T) 方法。

但是您始终可以将其他比较器(如 StructuralComparisons.StructuralEqualityComparer)提供给字典或方法(如 SequenceEqual)。

因此,两种方法之间的主要区别在于它们使用的相等性检查方法。 SequenceEqual 使用 IEquatable 接口方法进行检查,StructuralComparisons.StructuralEqualityComparer 使用 IStructuralEquatable 接口方法进行检查。因此,默认相等性检查需要两个比较项具有相同类型,但 StructuralEqualityComparer 不要求它们具有相同类型。顾名思义,它应该比较内容。


0
投票

linq 版本是最灵活的,它可以比较两个枚举。
StructuralComparisons.StructuralEqualityComparer 版本要求两个集合可以支持 IStructuralEquatable 接口。但我希望如果两个列表的长度不均匀,后者会更快。


0
投票
internal class StructuralEqualityComparer<T> : EqualityComparer<T> where T : IStructuralEquatable {
    public override bool Equals(T? x, T? y) {
        return StructuralComparisons.StructuralEqualityComparer.Equals(x, y);
    }

    public override int GetHashCode(T x) {
        return StructuralComparisons.StructuralEqualityComparer.GetHashCode(x);
    }
}

-1
投票

我认为 System.Linq 是你的朋友:

bool isEqual = Enumerable.SequenceEqual(array1, array2);
© www.soinside.com 2019 - 2024. All rights reserved.