Иногда удобно иметь отдельный метод, параметризованный каким-либо типом данных. Рассмотрим этот случай на примере метода сортировки. Известно, что «самого лучшего» алгоритма сортировки не существует. Для различных объема, диапазона, степени упорядоченности данных и распределения ключей оптимальными могут оказаться разные алгоритмы. Стандартные методы сортировки реализуют алгоритмы, которые хороши для большинства применений, но не для всех, поэтому может возникнуть необходимость реализовать собственный метод.
В листинге 13.4 приведен пример сортировки методом выбора. Алгоритм состоит в том, что сначала выбирается наименьший элемент массива и меняется местами с первым элементом, затем просматриваются элементы, начиная со второго, и наименьший из них меняется местами со вторым элементом, и т. д., всего п - 1 раз. На последнем проходе цикла при необходимости меняются местами предпоследний и последний элементы массива.
Листинг 13.4. Сортировка выбором
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Sort<T>(ref T[] a) // 1
where T: IComparable<T> // 2
{
T buf;
int n = a.Length;
for (int i = 0; i < n - 1; ++i)
{
int im = i;
for (int j = i + 1; j < n; ++j)
if (a[j].CompareTo(a[im]) < 0) im = j; // 3
buf = a[i];
a[i] = a[im];
a[im] = but;
}
}
static void Main()
{
int[] a = { 1, 6, 4, 2, 7, 5, 3 };
Sort<int>(ref a); // 4
foreach (int elem in a)
Console.WriteLine(elem);
doubled b = { 1.1, 5.2, 5.21, 2, 7, 6, 3 };
Sort(ref b); // 5
foreach (double elem in b)
Console.WriteLine(elem);
string[] s = { "qwe", "qwer", "df", "asd" };
Sort(ref s); //6
foreach (string elem in s)
Console.WriteLine(elem);
}
}
}
Метод параметризован типом, на который накладывается ограничение (оператор 2), чтобы объекты класса-аргумента можно было сравнивать друг с другом с помощью метода CompareTo, использованного в операторе 3.
В главной программе (методе Main) метод Sort вызывается двумя способами: с явным указанием параметра-типа (оператор 4) и без указания параметра (операторы 5 и 6). Во втором случае компилятор по типу переданного в метод параметра самостоятельно определяет, какой именно тип используется при инстанцировании.
ПРИМЕЧАНИЕ
Параметры-типы могут использоваться в списке параметров, возвращаемом типе и в теле универсального метода.
Итак, параметризованные типы и методы позволяют:
□ описывать способы хранения и алгоритмы обработки данных независимо от
типов данных;
□ выполнять контроль типов во время компиляции, а не исполнения программы;
□ увеличить скорость обработки данных за счет исключения операций упаков
ки, распаковки и преобразования типа.
Как уже упоминалось, помимо классов-прототипов и обобщенных методов можно описать параметризованные интерфейсы, структуры и делегаты.
В помощью параметризованных интерфейсов можно определить список функций, которые могут быть реализованы различным образом для разных классов, реализующих эти интерфейсы. Параметризованные интерфейсы можно реализовывать в классе-прототипе, используя в качестве аргументов интерфейса параметры типа, реализующего интерфейс, или в обычном классе, подставляя в качестве параметров интерфейса конкретные типы.
Параметризованные делегаты позволяют создавать обобщенные алгоритмы, логику которых можно изменять передаваемыми в качестве параметров делегатами.