我有 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..
我应该什么时候使用每一个?
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 版本,因为它更具可读性。
我刚刚有一个相关的问题,发现这个问题实际上从未得到正确的回答。结构和顺序之间存在差异 - 第一个比较是深入的,而第二个则不是。
这个简单的代码演示并产生
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));
名称“序列”暗示一维主义,因此名称选择是合适的。
.NET 中的标准相等性检查使用 EqualityComparer.Default 进行比较。例如,您在那里编写的字典或 SequenceEqual 方法默认使用 EqualityComparer.Default。并且该比较器在存在 IEquatable 接口实现的情况下使用 Equals(object) 方法或 Equals(T) 方法。
但是您始终可以将其他比较器(如 StructuralComparisons.StructuralEqualityComparer)提供给字典或方法(如 SequenceEqual)。
因此,两种方法之间的主要区别在于它们使用的相等性检查方法。 SequenceEqual 使用 IEquatable 接口方法进行检查,StructuralComparisons.StructuralEqualityComparer 使用 IStructuralEquatable 接口方法进行检查。因此,默认相等性检查需要两个比较项具有相同类型,但 StructuralEqualityComparer 不要求它们具有相同类型。顾名思义,它应该比较内容。
linq 版本是最灵活的,它可以比较两个枚举。
StructuralComparisons.StructuralEqualityComparer 版本要求两个集合可以支持 IStructuralEquatable 接口。但我希望如果两个列表的长度不均匀,后者会更快。
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);
}
}
我认为 System.Linq 是你的朋友:
bool isEqual = Enumerable.SequenceEqual(array1, array2);