IStructuralEquatable cho phép so sánh bằng cấu trúc (structural equality) thay vì so sánh tham chiếu (reference equality). Hai đối tượng bằng nhau về mặt cấu trúc nếu các phần tử tương ứng của chúng bằng nhau.
Interface này được implement bởi: Array, Tuple<T> và các generic tuple classes.
Hai phương thức
| Phương thức | Mô tả |
|---|---|
Equals(object other, IEqualityComparer comparer) |
Xác định đối tượng hiện tại có bằng cấu trúc với other không, dùng comparer để so sánh từng phần tử. |
GetHashCode(IEqualityComparer comparer) |
Trả về hash code dựa trên cấu trúc, dùng comparer cho từng phần tử. |
Ví dụ: So sánh Tuple và Array
using System;
using System.Collections;
class Program
{
static void Main()
{
// Tuple structural equality
var tuple1 = Tuple.Create(26.3, double.NaN, 35.6);
var tuple2 = Tuple.Create(26.3, double.NaN, 35.6);
var tuple3 = Tuple.Create(26.3, 0.0, 35.6);
IStructuralEquatable eq1 = tuple1;
Console.WriteLine($"tuple1 == tuple2 (NaN==NaN): {eq1.Equals(tuple2, EqualityComparer<object>.Default)}"); // True
Console.WriteLine($"tuple1 == tuple3 (NaN!=0): {eq1.Equals(tuple3, EqualityComparer<object>.Default)}"); // False
// Array structural equality
int[] arr1 = { 1, 2, 3 };
int[] arr2 = { 1, 2, 3 };
int[] arr3 = { 1, 2, 4 };
IStructuralEquatable eqArr = arr1;
Console.WriteLine($"\narr1 == arr2: {eqArr.Equals(arr2, EqualityComparer<object>.Default)}"); // True
Console.WriteLine($"arr1 == arr3: {eqArr.Equals(arr3, EqualityComparer<object>.Default)}"); // False
// HashCode structural
Console.WriteLine($"\nHashCode arr1: {eqArr.GetHashCode(EqualityComparer<object>.Default)}");
Console.WriteLine($"HashCode arr2: {((IStructuralEquatable)arr2).GetHashCode(EqualityComparer<object>.Default)}");
}
}
Kết quả
tuple1 == tuple2 (NaN==NaN): True tuple1 == tuple3 (NaN!=0): False arr1 == arr2: True arr1 == arr3: False HashCode arr1: 123456789 HashCode arr2: 123456789
Đặc điểm quan trọng
- Structural equality: So sánh từng phần tử theo thứ tự, dùng comparer cung cấp.
EqualityComparer<T>.DefaultdùngIEquatable<T>nếu có, fallbackobject.Equals.- NaN handling:
double.NaN == double.NaNlàfalsetheo IEEE, nhưngEqualityComparer<double>.Default.Equals(NaN, NaN)trả vềtrue(structural equality coi NaN bằng NaN). - Dùng cho: Tuple, Array, custom collection implement
IStructuralEquatable.
So sánh với IEquatable & IEqualityComparer
| Interface | Mục đích | Dùng khi |
|---|---|---|
IEquatable<T> | Type định nghĩa cách so sánh chính của chính nó | Value types, DTO, Entity (primary equality) |
IEqualityComparer<T> | So sánh bên ngoài, nhiều cách so sánh | Dictionary key, HashSet, LINQ Distinct/GroupBy |
IStructuralEquatable | So sánh cấu trúc cho composite types (tuple, array) | Tuple, Array, custom structural types |