Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Операторы сравнения




(Equality и Inequality)

Операторы позволяют выяснить, ссылаются ли два делегата на одну и ту же функцию.

public static bool operator == (Delegate d1, Delegate d2);public static bool operator!= (Delegate d1, Delegate d2);

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

MulticastDelegate.Combine и MulticastDelegate.Remove

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

// Объединяет два делегата в один.public static Delegate Delegate.Combine(// Первый делегат. Delegate, // Второй делегат. Delegate);// Объединяет произвольное количество делегатов в один.public static Delegate Delegate.Combine(// Массив делегатов, которые будут // объединены в один. Delegate[]);

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

Наряду с возможностью объединения нескольких делегатов в один, существует обратная операция — изъятия указанных методов из списка вызовов некоторого делегата.

// Позволяет изъять из делегата связь с определенными функциями, // представленные также делегатами.public static Delegate Delegate.Remove(// Делегат-источник. Delegate source, // Функции, связанные с этим делегатом, // будут изъяты из делегата-источника. Delegate value);

Рассмотренный метод, также как и метод Combine, не изменяет значение параметров, переданных ему. Он создает абсолютно новый делегат, в который помещает результаты своей работы.

Разработчики среды.NET решили, что простым программистам будет затруднительно использовать эти методы, в силу их нетривиальности. Поэтому в компилятор C# были введены специальные средства поддержки делегатов. Вы можете оперировать с делегатами при помощи обычных операций сложения и вычитания (+,-,+=,-=). При этом компилятор автоматически будет генерировать код, обращающийся к методам Combine и Remove.

Для наглядности приведем пример, демонстрирующий работу с делегатами, ссылающихся на несколько методов (листинг 6).

Листинг 6. Работа с делегатами, ссылающимися на несколько методов.

using System; class App{ delegate void MyDelegate(string s); // Это функция, на которую мы будем ссылаться при помощи // экземпляра делегата. static void MyHandler(string s) { // Просто выведем на консоль аргумент, полученный нашей // функцией. Console.WriteLine(s); } static void Main() { // Создадим экземпляр делегата, описанного ранее. // В качестве единственного параметра конструктора // передадим ссылку на метод MyHandler. MyDelegate del = new MyDelegate(MyHandler); // Создадим новый делегат и скомбинируем его // с ранее созданным делегатом. del += new MyDelegate(MyHandler); // То же самое можно сделать следующим образом. del = del + new MyDelegate(MyHandler); // А теперь уберем из списка вызова делегата // одну из ссылок на метод MyHanlder. del -= new MyDelegate(MyHanlder); // Затем обратимся к конечному делегату, естественно, // что при этом по цепочке будут вызваны все методы, // связанные с ним. del("Hello, world!"); }};

В результате работы приложения на консоль будут выведены следующие строки.

Hello, World!Hello, World!

Обратите внимание, что функция была вызвана два раза, хотя мы добавляли ее в список вызова делегата три раза. Но если учесть, что мы один раз изъяли ее из списка вызова, то все становится понятно. Интересно, что в списке вызова делегата все методы одинаковы, но этот факт для сервисов, оперирующих с делегатами, не имеет никакого значения.

Компилятор преобразует арифметические операции над делегатами в обращения к методам Combine и Remove. Чтобы наглядно продемонстрировать это, приведу листинг функции Main на языке IL, который получился после транслирования исходного кода компилятором языка C# (листинг 7).

Листинг 7. Код функции Main на языке IL.

.method private hidebysig static void Main() cil managed{.entrypoint.maxstack 4.locals init (class App/MyDelegate V_0) // Загружаем нулевой указатель — функция статическая, // не привязанная к экземпляру объекта. ldnull // Загружаем указатель на функцию. ldftn void App::MyHandler(string) // Создаем экземпляр делегата. newobj instance void App/MyDelegate::.ctor(object, native int) stloc.0 ldloc.0 // Создаем еще один точно такой же делегат с одним // методом в списке вызова. ldnull ldftn void App::MyHandler(string) newobj instance void App/MyDelegate::.ctor(object, native int) // Здесь как раз и происходит комбинирование делегатов, // на уровне языка С# это выглядело как оператор сложения (+=). call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) castclass App/MyDelegate stloc.0 ldloc.0 // Создаем еще один точно такой же делегат с одним // методом в списке вызова. ldnull ldftn void App::MyHandler(string) newobj instance void App/MyDelegate::.ctor(object, native int) // Здесь как раз и происходит комбинирование делегатов, // на уровне языка С# это выглядело как оператор сложения (+). call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) castclass App/MyDelegate stloc.0 ldloc.0 // Создаем еще один точно такой же делегат с одним // методом в списке вызова. ldnull ldftn void App::MyHandler(string) newobj instance void App/MyDelegate::.ctor(object, native int) // А здесь происходит изъятие метода из списка вызова делегата, // на уровне языка С# это выглядело как оператор вычитания (-=). call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) castclass App/MyDelegate stloc.0 ldloc.0 ldstr "Hello, world!" // А здесь происходит обращение к делегату. // Более подробно этот момент рассмотрим несколько позднее, // хотя, взглянув на следующую строку, вы можете обо всем // догадаться самостоятельно. callvirt instance void App/MyDelegate::Invoke(string) ret}

Понимая, что чтение IL-листингов может быть для некоторых читателей несколько утомительно, приведем код примера на языке C#, напрямую использующего методы Combine и Remove (листинг 8).

Листинг 8. Пример, явно использующий методы Combine и Remove.

using System; class App{ delegate void MyDelegate(string s); // Это функция, на которую мы будем ссылаться при помощи // экземпляра делегата. static void MyHandler(string s) { // Просто выведем на консоль аргумент, полученный нашей // функцией. Console.WriteLine(s); } // Точка входа в приложение. static void Main() { // Создадим экземпляр делегата, описанного выше. // В качестве единственного параметра конструктора // передадим ссылку на метод MyHandler. MyDelegate del = new MyDelegate(MyHandler); // Создадим новый делегат и скомбинируем его // с ранее созданным делегатом. //del += new MyDelegate(MyHandler); del = (MyDelegate)Delegate.Combine(del,new MyDelegate(MyHandler)); // То же самое можно сделать следующим образом. // del = del + new MyDelegate(MyHandler); del = (MyDelegate)Delegate.Combine(del,new MyDelegate(MyHandler)); // А теперь уберем из списка вызова делегата // одну из ссылок на метод MyHanlder. //del -= new MyDelegate(MyHanlder); del = (MyDelegate)Delegate.Remove(del,new MyDelegate(MyHandler)); // А так мы вызовем функцию через делегат. // Как видите, все просто, мы можем пользоваться // экземпляром делегата как функцией. del("Hello, world!"); }};

Результат работы данного примера нисколько не будет отличаться от предыдущего.

Hello, World!Hello, World!

Таким образом, использование методов Combine, Remove и арифметических операций, предоставляемых компилятором, по сути дела, ничем не отличается. Разве что обращение ко вторым более удобно, и программы, написанные с их использованием, читаются гораздо легче.




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


Дата добавления: 2014-01-07; Просмотров: 285; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.011 сек.