Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Interface IStructuralEquatable trong C#

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ứcMô 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>.Default dùng IEquatable<T> nếu có, fallback object.Equals.
  • NaN handling: double.NaN == double.NaN là false theo IEEE, nhưng EqualityComparer<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

InterfaceMục đíchDù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ánhDictionary key, HashSet, LINQ Distinct/GroupBy
IStructuralEquatableSo sánh cấu trúc cho composite types (tuple, array)Tuple, Array, custom structural types