Делегаты и события

Press any key to continue

Привет

Введите строку символов

Строка: Привет

 

Если оператор is встречается в теле цикла, то, т.к. проверка совместимости типа достаточно медленная операция, возможны относительно большие временные издержки. Для уменьшения временных затрат рекомендуется использовать оператор приведения типа as, который синтаксически записывается следующим образом:

 

type ob = выражение as type

 

Выражение приводится к типу, указанному справа от оператора as. Если операция проведена успешно, то возвращается ссылка на type, в противном случае null.

Функцию Main() из предыдущего примера можно переписать с использованием оператора as следующим образом:

static void Main(string[] args)

{

CB pb = new CB();

CD pD = new CD();

pb.MySet();

IOutInp pI = pb as IOutInp; // приведение к типу

if(pI != null)

{

pb.Put();

pb.Set();

pb.Put();

}

 

else

{

Console.WriteLine("Error");

}

}

 

Как видно из примера, проверка, с помощью оператора as, реализует ли объект pb интерфейс IOutInp, производится один раз. Результат проверки запоминается в переменной pI, если интерфейс реализован, то pI не равно null. Значение переменной pI, затем можно многократно использовать при необходимости проверки правомочности обращения к данному интерфейсу данного объекта.

Вопросы:

1. Какой класс называется абстрактным?

2. Может ли абстрактный класс содержать реализацию кода?

3. Для каких целей создаются абстрактные классы?

4. Какая спецификация доступа устанавливается в интерфейсе по умолчанию?

5. Может ли интерфейс содержать реализацию кода?

6. Поддерживают ли интерфейсы множественное наследование?

7. Какие функции могут являться членами интерфейса?

8. Какие операторы используются для проверки, реализует ли класс данный интерфейс?


 

В предшествующих языках, таких как C и C++, можно получить адрес функции и затем вызвать ее через указатель. Этот указатель можно передать, какой либо функции, в качестве параметра. Такая возможность широко применяется для реализации, так называемых, обратных вызовов функций. Применение указателей на функции, сложно для понимания и их использование, часто является источником многочисленных ошибок.

Для передачи ссылки на методы в качестве параметров другим методам в язык C# введен новый тип данных – делегат.

По своей структуре делегат - это объект, который ссылается на метод, то есть делегат указывает на адрес области памяти, являющейся точкой входа в метод. С помощью делегата можно вызвать метод, на который он указывает. В процессе выполнения программы делегату можно присвоить ссылку на другой метод. Это дает возможность определять во время выполнения программы, какой из методов должен быть вызван. Существенным моментом, является то, что в отличие от указателей, делегаты безопасны по типу. Кроме того, с помощью делегата, в отличие от указателей, которые работают только в адресном пространстве одного процесса, можно передать управление другому процессу или даже удаленному объекту.

Делегаты реализуются как экземпляры классов, производных от библиотечного класса System.Delegate. Для создания делегата необходимо выполнит два шага.

На первом шаге необходимо объявить с помощью ключевого слова delegate новый тип данных. При этом сигнатура объявления нового типа должна полностью соответствовать сигнатуре метода, который он будет представлять.

Например, делегат должен представлять метод класса СА, имеющий следующий заголовок:

 

static int min(int x, int y),

 

тогда объявление делегата может выглядеть, следующим образом:

 

delegate int LpFunc(int a, int b);

 

где LpFunc имя делегата является именем типа, который может представлять (инкапсулировать) любой метод возвращающий тип int и принимающий два параметра типа int .

 

На втором шаге мы должны создать экземпляр типа ( в нашем случае LpFunc) для хранения сведений о представляемом им методе. Для этого конструктору типа передается имя метода, который он будет представлять:

 

LpFunc pfnk = new LpFunk(CA.min);

 

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

Использование делегата демонстрируется в следующем примере:

 

using System;

 

namespace ConsoleApplication15

{

class MathOprt

{

public static void Sub(double var1,double var2)

{

double rslt = var1-var2;

Console.WriteLine("{0}-{1} = {2}",var1,var2,rslt);

 

}

 

public static void Add(double var1,double var2)

{

double rslt = var1+var2;

Console.WriteLine("{0}+{1} = {2}",var1,var2,rslt);

 

}

}

 

delegate void DblOp(double x,double y); //объявление делегата

 

class Class1

{

 

static void Prc(DblOp oprt, double vr1,double vr2)

{

Console.WriteLine("*********");

oprt(vr1,vr2);

}

static void Main(string[] args)

{

DblOp [] operations = // создание экземпляров делегата

{

new DblOp(MathOprt.Add),

new DblOp(MathOprt.Sub)

};

for (int j=0; j<2; j++)

{

Prc(operations[j],4.0,2.0);

Prc(operations[j],9.94,5.45);

}

}

}

}

 

Результат выполнения программы:

 

*********

4+2 = 6

*********

9,94+5,45 = 15,39

*********

4-2 = 2

*********

9,94-5,45 = 4,49