Этой ссылке на делегат будет присвоен метод,



// передаваемый конструктору класса 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 в следующей строке кода.

 

public interface ISeries<T> {

 

Как упоминалось выше, для объявления обобщенного интерфейса используется такой же синтаксис, что и для объявления обобщенного класса.

А теперь обратите внимание на следующее объявление класса ByTwos, реализующего интерфейс ISeries.

 

class ByTwos<T> : ISeries<T> {

 

Параметр типа Т указывается не только при объявлении класса ByTwos, но и при объявлении интерфейса ISeries. И это очень важно. Ведь класс, реализующий обобщенный вариант интерфейса, сам должен быть обобщенным. Так, приведенное ниже объявление недопустимо, поскольку параметр типа Т не определен.

 

class ByTwos : ISeries<T> { // Неверно!

 

Аргумент типа, требующийся для интерфейса ISeries, должен быть передан классу ByTwos. В противном случае интерфейс никак не сможет получить аргумент типа.

Далее переменные, хранящие текущее значение в последовательном ряду (val) и его начальное значение (start), объявляются как объекты обобщенного типа Т. После этого объявляется делегат IncByTwo. Этот делегат определяет форму метода, используемого для увеличения на два значения, хранящегося в объекте типа Т. Для того чтобы в классе ByTwos могли обрабатываться данные любого типа, необходимо каким-то образом определить порядок увеличения на два значения каждого типа данных. Для этого конструктору класса ByTwos передается ссылка на метод, выполняющий увеличение на два. Эта ссылка хранится в переменной экземпляра делегата incr. Когда требуется сгенерировать следующий элемент в последовательном ряду, этот метод вызывается с помощью делегата incr.

А теперь обратите внимание на класс ThreeD. В этом классе инкапсулируются координаты трехмерного пространства (X,Z,Y). Его назначение — продемонстрировать обработку данных типа класса в классе ByTwos.

Далее в классе GenIntfDemo объявляются три метода увеличения на два для объектов типа int, double и ThreeD. Все эти методы передаются конструктору класса ByTwos при создании объектов соответствующих типов. Обратите особое внимание на приведенный ниже метод ThreeDPlusTwo().

 

// Определить метод увеличения на два каждого

// последующего значения координат объекта типа 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);

}

 

В этом методе сначала проверяется, содержит ли переменная экземпляра v пустое значение (null). Если она содержит это значение, то метод возвращает новый объект типа ThreeD со всеми обнуленными полями координат. Ведь дело в том, что переменной v по умолчанию присваивается значение типа default(Т) в конструкторе класса ByTwos. Это значение оказывается по умолчанию нулевым для типов значений и пустым для типов ссылок на объекты. Поэтому если предварительно не был вызван метод SetStart(), то перед первым увеличением на два переменная v будет содержать пустое значение вместо ссылки на объект. Это означает, что для первого увеличения на два требуется новый объект.

На параметр типа в обобщенном интерфейсе могут накладываться ограничения таким же образом, как и в обобщенном классе. В качестве примера ниже приведен вариант объявления интерфейса ISeries с ограничением на использование только ссылочных типов.

 

public interface ISeries<T> where T : class {

 

Если реализуется именно такой вариант интерфейса ISeries, в реализующем его классе следует указать то же самое ограничение на параметр типа Т, как показано ниже.

 

class ByTwos<T> : ISeries<T> where T : class {

 

В силу ограничения ссылочного типа этот вариант интерфейса ISeries нельзя применять к типам значений. Поэтому если реализовать его в рассматриваемом здесь примере программы, то допустимым окажется только объявление ByTwos<ThreeD>, но не объявления ByTwos<int> и ByTwos<double>.

 

 


Дата добавления: 2019-02-12; просмотров: 262; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!