C# 4.0 полное руководство - 2011
Шрифт:
// Требуется обобщенный интерфейс IEquatable<T>.
public static bool IsIn<T>(T what, T[] obs) where T : IEquatable<T> { foreach(T v in obs)
if(v.Equals(what)) // Применяется метод Equals. return true;
return false;
}
Обратите внимание в приведенном выше примере на применение следующега ограничения.
where Т : IEquatable<T>
Это ограничение гарантирует, что только те типы, в которых реализован интерфейс IEquatable, являются
Для определения относительного порядка следования двух элементов применяется интерфейс I Comp а г able. У этого интерфейса имеются две формы: обобщенная и необобщенная. Обобщенная форма данного интерфейса обладает преимуществом обеспечения типовой безопасности, и поэтому мы рассмотрим здесь именно ее. Обобщенный интерфейс IComparable<T> объявляется следующим образом.
public interface IComparable<T>
Сравниваемый тип данных передается ему в качестве аргумента типа Т. В этом интерфейсе определяется метод CompareTo , как показано ниже.
int CompareTo(Т other)
В этом методе сравниваются вызывающий объект и другой объект, определяемый параметром other. В итоге возвращается нуль, если вызывающий объект оказывается больше, чем объект other; и отрицательное значение, если вызывающий объект оказывается меньше, чем объект other.
Для того чтобы воспользоваться методом CompareTo , необходимо указать ограничение, которое требуется наложить на аргумент типа для реализации обобщенного интерфейса IComparable<T>. А затем достаточно вызвать метод CompareTo , чтобы сравнить два экземпляра параметра типа.
Ниже приведен пример применения обобщенного интерфейса IComparable<T>. В этом примере вызывается метод InRange , возвращающий логическое значение true, если объект оказывается среди элементов отсортированного массива.
// Требуется обобщенный интерфейс IComparable<T>. В данном методе // предполагается, что массив отсортирован. Он возвращает логическое // значение true, если значение параметра what оказывается среди элементов // массива, передаваемых параметру obs.
public static bool InRange<T>(T what, T[] obs) where T : IComparable<T> { if(what.CompareTo(obs[0]) < 0 ||
what.CompareTo(obs[obs.Length-1]) > 0) return false; return true;
}
В приведенном ниже примере программы демонстрируется применение обоих методов Is In и InRange на практике.
// Продемонстрировать применение обобщенных // интерфейсов IComparable<T> и IEquatable<T>.
using System;
// Теперь в классе MyClass реализуются обобщенные // интерфейсы IComparable<T> и IEquatable<T>. class MyClass : IComparable<MyClass>, IEquatable<MyClass> { public int Val;
public MyClass(int x) { Val = x; }
// Реализовать обобщенный интерфейс IComparable<T>. public int CompareTo(MyClass other) {
return Val - other.Val; // Now, no cast is needed.
> \
// Реализовать обобщенный интерфейс IEquatable<T>.
public bool Equals(MyClass other) { return Val == other.Val;
}
// Переопределить метод Equals(Object).
public override bool Equals(Object obj) { if(obj is MyClass)
return Equals((MyClass) obj); return false;
}
// Переопределить метод GetHashCode.
public override int GetHashCode { return Val.GetHashCode ;
}
}
class CompareDemo {
// Требуется обобщенный интерфейс IEquatable<T>.
public static bool IsIn<T>(T what, T[] obs) where T : IEquatable<T> { foreach(T v in obs)
if(v.Equals(what)) // Применяется метод Equals return true;
return false;
}
// Требуется обобщенный интерфейс IComparable<T>. В данном методе // предполагается, что массив отсортирован. Он возвращает логическое // значение true, если значение параметра what оказывается среди элементов // массива, передаваемых параметру obs.
public static bool InRange<T>(T what, T[] obs) where T : IComparable<T> { if(what.CompareTo(obs[0]) < 0 ||
what.CompareTo(ob§[obs.Length-1]) > 0) return false; return true;
}
// Продемонстрировать операции сравнения, static void Main {
// Применить метод Isln к данным типа int. int[] nums = { 1, 2, 3, 4, 5 };
if(IsIn(2, nums))
Console.WriteLine("Найдено значение 2.");
if(Isln(99, nums))
Console.WriteLine("He подлежит выводу.");
// Применить метод Isln к объектам класса MyClass.
MyClass[] mcs = { new MyClass(1), new MyClass(2),
new MyClass(3), new MyClass(4) };
if(lsln(new MyClass(3), mcs))
Console.WriteLine("Найден объект MyClass(3).");
if(Isln(new MyClass(99), mcs))
Console.WriteLine("He подлежит выводу.");
// Применить метод InRange к данным типа int. if(InRange(2, nums))