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



ЗНАЕТЕ ЛИ ВЫ?

Базовые классы «System.MulticastDelegate» и «System.Delegate»

Поиск

 

Когда компилятор С# обрабатывает тип делегата, он автоматически генерирует запечатанный (sealed) класс, унаследованный от System.MulticastDelegate. Этот класс (в сочетании с его базовым классом System.Delegate) предоставляет необходимую инфраструктуру для делегата, чтобы хранить список методов, подлежащих вызову в более позднее время. Например, можно просмотреть делегат IntOperation из предыдущего примера с помощью утилиту IL DASM («Дизассемблер IL», файл ildasm.exe). Утилиту можно найти по умолчанию по следующему пути (для Windows 7): Пуск -> Все программы -> Microsoft Visual Studio 2010 -> Microsoft Windows SDK Tools -> Дизассемблер IL. Главное окно утилиты выглядит так:

 

Рис. 3. 1. Окно утилиты IL DASM (ildasm.exe)

 

Открываем EXE-файл скомпилированного приложения из предыдущего кода консольного приложения. На рисунке показан класс IntOperation, который будет сгенерирован для делегата IntOperation:

 

Рис. 3. 2. IL DASM: разбор ассемблерных действий делегата IntOperation

 

Как видим, сгенерированный компилятором класс IntOperation определяет три общедоступных метода. Invoke() — возможно, главный из них, поскольку он используется для синхронного вызова каждого из методов, поддерживаемых объектом делегата; это означает, что вызывающий код должен ожидать завершения вызова, прежде чем продолжить свою работу. Может показаться странным, что синхронный метод Invoke не должен вызываться явно в коде С#. Invoke() вызывается «за кулисами», когда применяется соответствующий синтаксис С#.

Методы BeginInvoke и EndInvoke предлагают возможность вызова текущего метода асинхронным образом, в отдельном потоке выполнения. Имеющим опыт в многопоточной разработке должно быть известно, что одной из основных причин, вынуждающих разработчиков создавать вторичные потоки выполнения, является необходимость вызова методов, которые требуют определенного времени для завершения. Хотя в библиотеках базовых классов.NET предусмотрено целое пространство имён, посвященное многопоточному программированию (System.Threading), делегаты предлагают эту функциональность в готовом виде.

 

Ниже показаны некоторые избранные методы System.MulticastDelegate:

 

public abstract class MulticastDelegate: Delegate

{

// Возвращает список методов, на которые "указывает" делегат

public sealed override Delegate[] GetlnvocationList();

// Перегруженные операции

public static bool operator == (MulticastDelegate d1, MulticastDelegate d2);

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

// Используются внутренне для управления списком методов, поддерживаемых делегатом

private IntPtr _invocationCount;

private object _invocationList;

}

 

Класс System.MulticastDelegate получает дополнительную функциональность от своего родительского класса System.Delegate. Ниже показан фрагмент определения класса:

 

public abstract class Delegate: ICloneable, ISerializable

{

// Методы Для взаимодействия со списком функций

public static Delegate Combine(params Delegate[] delegates);

public static Delegate Combine(Delegate a, Delegate b);

public static Delegate Remove(Delegate source, Delegate value);

public static Delegate RemoveAll(Delegate source, Delegate value);

// Перегруженные операции

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

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

// Свойства, показывающие цель делегата

public Methodlnfo Method { get; }

public object Target { get; }

}

Нельзя напрямую наследовать от этих базовых классов в коде (при попытке сделал это выдаётся ошибка компиляции). Тем не менее, при использовании ключевого слова delegate неявно создается класс, который «является» MulticastDelegate.

 

В следующей таблице описаны основные члены, общие ддя всех типов делегатов:

 

Член Назначение
Method Это свойство возвращает объект System.Reflection.Method, который представляет детали статического метода, поддерживаемого делегатом
Target Если метод, подлежащий вызову, определен на уровне объекта (т.е. не является статическим), то Target возвращает объект, представляющий метод, поддерживаемый делегатом. Если возвращенное Target значение равно null, значит, подлежащий вызову метод является статическим
Combine() Этот статический метод добавляет метод в список, поддерживаемый делегатом. В С# этот метод вызывается за счет использования перегруженной операции (+=) в качестве сокращенной нотации
GetlnvokationList() Этот метод возвращает массив типов System.Delegate, каждый из которых представляет определенный метод, доступный для вызова
Remove() RemoveAll() Эти статические методы удаляют метод (или все методы) из списка вызовов делегата. В С# метод Remove() может быть вызван неявно, посредством перегруженной операции (-=)

 

4. Групповое преобразование делегируемых методов

 

Ещё в версии С# 2.0 было внедрено специальное средство, существенно упрощающее синтаксис присваивания метода делегату. Это так называемое групповое преобразование методов, позволяющее присвоить имя метода делегату, не прибегая к оператору new или явному вызову конструктора делегата. Пример:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace LC_Console

{

// Создаём делегат

delegate int IntOperation(int i, int j);

 

class Program

{

// Организуем ряд методов

static int Sum(int x, int y)

{

return x + y;

}

 

static int Prz(int x, int y)

{

return x * y;

}

 

static int Del(int x, int y)

{

return x / y;

}

 

static void Main()

{

// Присваиваем имя метода обычным способом

IntOperation op1 = new IntOperation(Sum);

// Используем групповое преобразование

op1 = Sum;

int result = op1(5, 10);

Console.WriteLine("Сумма: " + result);

// Изменим ссылку на метод

op1 = Prz;

result = op1(5, 10);

Console.WriteLine("Произведение: " + result);

Console.WriteLine("Для продолжения нажмите любую клавишу...");

Console.ReadKey();

}

}

}

 

Синтаксис группового преобразования методов существенно упрощён по сравнению с прежним подходом к делегированию.

 



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 454; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.12.76.168 (0.009 с.)