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
for(int i=0; i < 5; i++)
Console.Write(intBT.GetNext() + " ");
Console.WriteLine();
// Продемонстрировать генерирование
// последовательного ряда значений типа double.
ByTwos
dblBT.SetStart(11.4);
for(int i=0; i < 5; i++)
Console.Write(dblBT.GetNext() + " ");
Console.WriteLine();
// Продемонстрировать генерирование последовательного ряда
// значений координат объекта типа ThreeD.
ByTwos
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
в следующей строке кода.
public interface ISeries
Как упоминалось выше, для объявления обобщенного интерфейса используется такой же синтаксис, что и для объявления обобщенного класса.
А теперь обратите внимание на следующее объявление класса ByTwos
, реализующего интерфейс ISeries
.
class ByTwos
Параметр типа Т указывается не только при объявлении класса ByTwos
, но и при объявлении интерфейса ISeries
. И это очень важно. Ведь класс, реализующий обобщенный вариант интерфейса, сам должен быть обобщенным. Так, приведенное ниже объявление недопустимо, поскольку параметр типа Т не определен.
class ByTwos : ISeries
Аргумент типа, требующийся для интерфейса ISeries
, должен быть передан классу ByTwos
. В противном случае интерфейс никак не сможет получить аргумент типа.
Далее переменные, хранящие текущее значение в последовательном ряду (val) и его начальное значение (start), объявляются как объекты обобщенного типа Т. После этого объявляется делегат IncByTwo
. Этот делегат определяет форму метода, используемого для увеличения на два значения, хранящегося в объекте типа Т. Для того чтобы в классе ByTwos
могли обрабатываться данные любого типа, необходимо каким-то образом определить порядок увеличения на два значения каждого типа данных. Для этого конструктору класса ByTwos
передается ссылка на метод, выполняющий увеличение на два. Эта ссылка хранится в переменной экземпляра делегата incr
. Когда требуется сгенерировать следующий элемент в последовательном ряду, этот метод вызывается с помощью делегата incr
.
А теперь обратите внимание на класс ThreeD
. В этом классе инкапсулируются координаты трехмерного пространства (X,Z,Y). Его назначение — продемонстрировать обработку данных типа класса в классе ByTwos
.