Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.pdf
Скачиваний:
65
Добавлен:
11.05.2015
Размер:
1.81 Mб
Скачать

public class LastFirstComparer : EqualityComparer<Customer>

{

public override bool Equals(Customer x, Customer y)

{

return x.LastName == y.LastName && x.FirstName == y.FirstName;

}

public override int GetHashCode(Customer obj)

{

return (obj.LastName + ";" + obj.FirstName).GetHashCode();

}

}

Статическое свойство EqualityComparer<T>.Default возвращает экземпляр EqualityComparer<T> для типа T. Этот экземпляр использует метод Equals(T) либо метод Equals(object) в зависимости от того, реализует ли тип T интерфейс

IEquatable<T>.

Ранее указывалось, что по умолчанию структуры реализуют равенство по значению: две структуры равны, если равны значения всех их соответствующих

элементов. Интерфейс System.Collections.IStructuralEquatable позволяет пе-

ренести данную семантику на другие типы. На платформе .NET этот интерфейс явно реализуют любые массивы и кортежи (классы вида System.Tuple<>).

public interface IStructuralEquatable

{

bool Equals(object other, IEqualityComparer comparer); int GetHashCode(IEqualityComparer comparer);

}

Передаваемый в метод Equals() объект comparer применяется к каждому индивидуальному элементу в составном объекте. Следующий пример демонстрирует использование IStructuralEquatable.

string[] low = "the quick brown fox".Split(); string[] high = "THE QUICK BROWN FOX".Split(); IStructuralEquatable se = low;

// переменная f равна true

bool f = se.Equals(high, StringComparer.InvariantCultureIgnoreCase);

6. Сравнение для выяснения порядка

Стандартным способом сравнения для выяснения порядка является реали-

зация типом интерфейсов IComparable и IComparable<T>:

public interface IComparable

{

int CompareTo(object other);

}

19

public interface IComparable<in T>

{

int CompareTo(T other);

}

Оба интерфейса предоставляют одинаковый функционал. Универсальный интерфейс IComparable<T> избавляет от необходимости упаковки при работе с типами значений. Метод x.CompareTo(y) должен возвращать любое положительное число, если x «больше» y, отрицательное число, если x «меньше» y, и ноль, если x и y равны.

Базовые типы реализуют обе версии интерфейса IComparable. В типе string метод CompareTo() выполняет чувствительное к регистру сравнение строк с учётом региональных стандартов. В некоторых базовых типах дополнительно определён статический метод сравнения Compare(). Например, string имеет перегруженные версии Compare(), которые принимают или элемент перечисления StringComparison, или булев флаг (игнорирование регистра) и объект

CultureInfo:

string s1 = "Strasse", s2 = "Straße"; // порядковое сравнение, i = -108

int i = string.Compare(s1, s2, StringComparison.Ordinal); // j = 0, так как в немецком языке такие слова равны

int j = string.Compare(s1, s2, false, new CultureInfo("de-DE"));

Кроме реализации IComparable и IComparable<T> тип может дополнительно перегружать операции < и >. Перегрузка операций сравнения обычно выполняется, если результат операции не зависит от контекста выполнения1.

bool isAfterDoomsday = DateTime.Now > new DateTime(2012, 12, 21);

Как и в случае проверки на равенство, сравнение для выяснения порядка можно выполнить при помощи подключаемых интерфейсов. Для порядкового сравнения предназначены интерфейсы IComparer<T> и IComparer (пространства

имён System.Collections.Generic и System.Collections).

public interface IComparer

{

int Compare(object x, object y);

}

public interface IComparer<in T>

{

int Compare(T x, T y);

}

1 Тип string не перегружает операции сравнения, так как результат может измениться в зависимости от текущих региональных стандартов.

20