I have 2 arrays :
int[] arr1 = new int[] { 1, 2, 3 };
int[] arr2 = new int[] { 1, 2, 3 };
I need to check if they are equal ( not by ref)
What is the difference between writing :
Console.WriteLine(arr1.SequenceEqual(arr2)); //true
vs
IStructuralEquatable eqArray1 = arr1;
Console.WriteLine(eqArray1.Equals(arr2, StructuralComparisons.StructuralEqualityComparer)); //true
both returns True..
When should I use each ?
The implementation of SequenceEqual
is kind of similar::
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;
This default SequenceEqual
method use default EqualityComparer<int>.Default
for int
which is value equality.
Array
implement IStructuralEquatable
with Equal
method:
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;
}
The IEqualityComparer
from input parameter is used, in here you input StructruralEqualityComparer
but int
does not implement IStructruralEquatable
, so it uses default comparer for int
which is value equality.
But, needless to input StructruralEqualityComparer
because int
is not structural, you should just use:
(arr1 as IStructuralEquatable).Equals(arr2, EqualityComparer<int>.Default);
It still works. You should use StructruralEqualityComparer
if item in array is structrural
So to sum up, the implementation for both is kind of the same, both iterate two array based on value equality of int
to make comparison.
I would prefer the LINQ verson since it is more readable.
I just had a related question and saw that this question was never actually answered properly. There is a difference between the structural and the sequence - the first comparison is deep and the second one is not.
This simple code demonstrates and produces 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));
The name "sequence" suggests one-dimensionalism so the name choice is appropriate.
Standard equality checks in .NET uses EqualityComparer.Default for comparisons. For example dictionaries or SequenceEqual method you have written there uses EqualityComparer.Default by default. And that comparer either uses Equals(object) method or Equals(T) method in presence of IEquatable interface implementation.
But you can always give other comparers like StructuralComparisons.StructuralEqualityComparer to dictionaries or methods such as SequenceEqual.
So, the main difference between two methods is the equality check method they use. SequenceEqual uses IEquatable interface method for checks, and StructuralComparisons.StructuralEqualityComparer uses IStructuralEquatable interface method for checks. And as a result, default equality checks need two of the compared items to be the same type but StructuralEqualityComparer doesn't require them to be same type. As the name suggests it is supposed to compare contents.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With