11.4.5 일반적인 동일성 비교와 순차성 비교
ValueTuple<…>은 IEquatable<T>와 IComparable<T>를 구현하는데, 이때 T는 ValueTuple<…>
그 자체가 사용된다. 즉, ValueTuple<T1, T2>는 IEquatable<ValueTupple<T1, T2>>와 IComparable<ValueTuple<T1, T2>>를 각기 구현한다.
그 외에도 제네릭 타입이 아닌 IComparable 인터페이스를 구현하고 object.Equals(object) 메서드를 아주 일반적인 방식으로 구현한다. 즉, Equals(object)는 비교 대상 타입이 다르면 false를 반환하고, CompareTo(object)는 비교 대상 타입이 다르면 ArgumentException을 던진다. 그 외의 다른 경우에는 IEquatable<T>와 IComparable<T> 구현체에 작업을 위임한다.
동일성 테스트는 튜플 요소의 타입 각각이 제공하는 동일성 비교 연산을 활용한다. 각각의 튜플 요소에 동일성 비교 연산을 이용하여 해시 코드를 생성하고, 이렇게 생성된 여러 개의 해시 코드를 타입별로 제공되는 결합 방식을 이용하여 튜플에 대한 해시 값으로 사용한다. 튜플 간의 순차성 비교 또한 튜플 요소별로 수행된다. 앞쪽에 위치한 요소가 뒤쪽에 있는 요소보다 더 중요한 것으로 다루어지므로 (1,5)는 (3,2)보다 작은 것으로 간주된다.
이러한 비교 연산을 활용하면 LINQ 코드를 작성할 때 한결 수월하다. (x, y) 좌표를 나타내는 (int, int) 튜플의 컬렉션이 있다고 가정해 보자. LINQ를 이용하면 손쉽게 중복이 제거된 컬렉션을 얻을 수 있다. 다음 코드를 보자.
예제 11-9 (x, y) 좌표 검색과 중복 제거 ▶ RegularComparisons.cs
var points = new[]
{
(1, 2), (10, 3), (-1, 5), (2, 1),
(10, 3), (2, 1), (1, 1)
};
var distinctPoints = points.Distinct();
Console.WriteLine($"{distinctPoints.Count()} distinct points");
Console.WriteLine("Points in order:");
foreach (var point in distinctPoints.OrderBy(p => p))
{
Console.WriteLine(point);
}