Шрифт:
Интервал:
Закладка:
В приведенном ниже примере программы демонстрируется применение делегата SomeOp с одним параметром типа Т. Этот делегат возвращает значение типа Т и принимает аргумент типа Т.
// Простой пример обобщенного делегата,
using System;
// Объявить обобщенный делегат,
delegate T SomeOp<T>(T v);
class GenDelegateDemo {
// Возвратить результат суммирования аргумента,
static int Sum(int v) {
int result = 0;
for (int i = v; i > 0; i--) result += i;
return result;
}
// Возвратить строку, содержащую обратное значение аргумента,
static string Reflect(string str) {
string result = "";
foreach (char ch in str) result = ch + result;
return result;
}
static void Main() {
// Сконструировать делегат типа int.
SomeOp<int> intDel = Sum;
Console.WriteLine(intDel(3));
// Сконструировать делегат типа string.
SomeOp<string> strDel = Reflect;
Console.WriteLine(strDel("Привет"));
}
}
Эта программа дает следующий результат.
6
тевирП
Рассмотрим эту программу более подробно. Прежде всего обратите внимание на следующее объявление делегата SomeOp.
delegate Т SomeOp<T>(T v);
Как видите, тип Т может служить в качестве возвращаемого типа, несмотря на то, что параметр типа Т указывается после имени делегата SomeOp.
Далее в классе GenDelegateDemo объявляются методы Sum() и Reflect(), как показано ниже.
static int Sum(int v) {
static string Reflect(string str) {
Метод Sum() возвращает результат суммирования целого значения, передаваемого в качестве аргумента, а метод Reflect() — символьную строку, которая получается обращенной по отношению к строке, передаваемой в качестве аргумента.
В методе Main() создается экземпляр intDel делегата, которому присваивается ссылка на метод Sum().
SomeOp<int> intDel = Sum;
Метод Sum() принимает аргумент типа int и возвращает значение типа int, поэтому он совместим с целочисленным экземпляром делегата SomeOp.
Аналогичным образом создается экземпляр strDel делегата, которому присваивается ссылка на метод Reflect().
SomeOp<string> strDel = Reflect;
Метод Reflect() принимает аргумент типа string и возвращает результат типа string, поэтому он совместим со строковым экземпляром делегата SomeOp.
В силу присущей обобщениям типовой безопасности обобщенным делегатам нельзя присваивать несовместимые методы. Так, следующая строка кода оказалась бы ошибочной в рассматриваемой здесь программе.
SomeOp<int> strDel = Reflect; //Ошибка!
Ведь метод Reflect() принимает аргумент типа string и возвращает результат типа string, а следовательно, он несовместим с целочисленным экземпляром делегата SomeOp.
Обобщенные интерфейсы
Помимо обобщенных классов и методов, в C# допускаются обобщенные интерфейсы. Такие интерфейсы указываются аналогично обобщенным классам. Ниже приведен измененный вариант примера из главы 12, демонстрирующего интерфейс ISeries. (Напомним, что ISeries является интерфейсом для класса, генерирующего последовательный ряд числовых значений.) Тип данных, которым оперирует этот интерфейс, теперь определяется параметром типа.
// Продемонстрировать применение обобщенного интерфейса.
using System;
public interface ISeries<T> {
T GetNext(); // возвратить следующее по порядку число
void Reset(); // генерировать ряд последовательных чисел с самого начала
void SetStart(T v); // задать начальное значение
}
//Реализовать интерфейс ISeries.
class ByTwos<T> : ISeries<T> {
T start;
T val;
// Этот делегат определяет форму метода,
// вызываемого для генерирования
// очередного элемента в ряду последовательных значений.
public delegate T IncByTwo(T v);
// Этой ссылке на делегат будет присвоен метод,
// передаваемый конструктору класса ByTwos.
IncByTwo incr;
public ByTwos(IncByTwo incrMeth) {
start = default(T);
val = default(T);
incr = incrMeth;
}
public T GetNext() {
val = incr(val);
return val;
}
public void Reset() {
val = start;
}
public void SetStart(T v) {
start = v;
val = start;
}
}
class ThreeD {
public int x, y, z;
public ThreeD(int a, int b, int c) {
x = a;
y = b;
z = c;
}
}
class GenIntfDemo {
// Определить метод увеличения на два каждого
// последующего значения типа int.
static int IntPlusTwo(int v) {
return v + 2;
}
// Определить метод увеличения на два каждого
// последующего значения типа double.
static double DoublePlusTwo(double v) {
return v + 2.0;
}
// Определить метод увеличения на два каждого
// последующего значения координат объекта типа ThreeD.
static ThreeD ThreeDPlusTwo(ThreeD v) {
if(v==null) return new ThreeD(0, 0, 0);
else return new ThreeD(v.x + 2, v.y + 2, v.z + 2);
}
static void Main() {
// Продемонстрировать генерирование
// последовательного ряда значений типа int.
ByTwos<int> intBT = new ByTwos<int>(IntPlusTwo);
for(int i=0; i < 5; i++)
Console.Write(intBT.GetNext() + " ");
Console.WriteLine();
// Продемонстрировать генерирование
// последовательного ряда значений типа double.
ByTwos<double> dblBT = new ByTwos<double>(DoublePlusTwo);
dblBT.SetStart(11.4);
for(int i=0; i < 5; i++)
Console.Write(dblBT.GetNext() + " ");
Console.WriteLine();
// Продемонстрировать генерирование последовательного ряда
// значений координат объекта типа ThreeD.
ByTwos<ThreeD> ThrDBT = new ByTwos<ThreeD>(ThreeDPlusTwo);
ThreeD coord;
for(int i=0; i < 5; i++) {
coord = ThrDBT.GetNext();
Console.Write(coord.x + "," +
coord.y + "," +
coord.z + " ");
}
Console.WriteLine();
}
}
Этот код выдает следующий результат.
2 4 6 8 10
13.4 15.4 17.4 19.4 21.4
0,0,0 2,2,2 4,4,4 6,6,6 8,8,8
В данном примере кода имеется ряд любопытных моментов. Прежде всего обратите внимание на объявление интерфейса ISeries в следующей строке кода.
- QT 4: программирование GUI на С++ - Жасмин Бланшет - Программирование
- C# для профессионалов. Том II - Симон Робинсон - Программирование
- ИНФОРМАЦИОННАЯ ТЕХНОЛОГИЯ. РУКОВОДСТВО ПО УПРАВЛЕНИЮ ДОКУМЕНТИРОВАНИЕМ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ - ГОССТАНДАРТ РОССИИ - Программирование
- Управление исходными текстами. Часть 1. Краткое руководство по CVS - Илья Рыженков - Программирование
- Гибкое управление проектами и продуктами - Борис Вольфсон - Программирование
- Каждому проекту своя методология - Алистэр Коуберн - Программирование
- Разработка ядра Linux - Роберт Лав - Программирование
- Как спроектировать современный сайт - Чои Вин - Программирование
- Творческий отбор. Как создавались лучшие продукты Apple во времена Стива Джобса - Кен Косиенда - Прочая околокомпьтерная литература / Интернет / Программирование
- Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT. Часть 2 - Александр Фролов - Программирование