Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Обобщенные делегаты

Assert срабатывает только в режиме Debug | Потоки ввода-вывода | Автоматическое управление памятью ссылочных данных | Упаковка и разупаковка данных | Типы данных со значением null | Конструкторы и деструкторы | Частично определяемые классы и их назначение | Механизм вызова событий | Создание пользовательских обобщенных коллекций | Создание обобщенных интерфейсов |


Читайте также:
  1. Обобщенные критерии качества ПО.
  2. Обобщенные целочисленные переменные

Предположим, например, что требуется определить делегат, который сможет вызывать любой метод, возвращающий void и принимающий один аргумент. Если аргумент может меняться, это можно учесть с помощью параметра типа. Для примера рассмотрим следующий программный код (обратите внимание на то, что целевые объекты делегата регистрируются как с помощью “традиционного” синтаксиса делегата, так и с помощью группового преобразования метода).

 

namespace GenericDelegate{ // Этот обобщенный делегат может вызвать любой метод, // возвращающий void и принимающий один параметр. public delegate void MyGenericDelegate<T>(T arg); class Program { static void Main(string[] args) { Console.WriteLine("***** Обобщенные делегаты *****\n"); // Регистрация цели с помощью 'традиционного' // синтаксиса делегата. MyGenericDelegate<string> strTarget = new MyGenericDelegate<string>(StringTarget); strTarget("Некоторые строковые данные"); // Регистрация цели с помощью // группового преобразования метода. MyGenericDelegate<int> intTarget = IntTarget; intTarget(9); Console.ReadLine(); } static void StringTarget(string arg) { Console.WriteLine("arg в верхнем регистре: {0}", arg.ToUpper()); } static void IntTarget(int arg) { Console.WriteLine("++arg: {0}", ++arg); } }}

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

// Создание экземпляра MyGenericDelegate<T> // со значением string для параметра типа. MyGenericDelegate<string> strTarget = new MyGenericDelegate<string>(StringTarget); strTarget("Некоторые строковые данные");

С учетом формата объекта strTarget метод StringTarget() должен теперь получить в качестве параметра одну строку.

static void StringTarget(string arg){ Console.WriteLine("arg в верхнем регистре: {0}", arg.ToUpper());}

Как видите, обобщенные делегаты предлагают более гибкий подход для указания вызываемых методов.

В рамках.NET 1.1 аналогичного результата можно достичь с помощью базового System.Object.

public delegate void MyDelegate(object arg);

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

 

class Program{ static void Main(string[] args) {... // Регистрация цели с помощью // 'традиционного' синтаксиса делегата. MyDelegate d = new MyDelegate(MyTarget); d("Дополнительные строковые данные"); // Регистрация цели с помощью // группового преобразования метода. MyDelegate d2 = MyTarget; d2(9); // Проблема объектного образа.... } // Ввиду отсутствия типовой безопасности мы должны // определить соответствующий тип до преобразования. static void MyTarget(object arg) { if(arg is int) { int i = (int)arg; // Проблема восстановления значения. Console.WriteLine("++arg: {0}", ++i); } if(arg is string) { string s = (string)arg; Console.WriteLine("arg в верхнем регистре: {0}", s.ToUpper()); } }}

Когда вы посылаете целевому объекту тип, характеризуемый значением, это значение (конечно же) “упаковывается” в объект и “распаковывается” после его получения целевым методом. Точно также, поскольку поступающий параметр может быть всем чем угодно, вы должны динамически проверить соответствующий тип перед тем, как выполнить преобразование. С помощью обобщенных делегатов вы можете получить всю необходимую гибкость без “проблем”.


Дата добавления: 2015-11-16; просмотров: 62 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Установка ограничений на параметры обобщенных классов| Несколько слов о вложенных делегатах

mybiblioteka.su - 2015-2024 год. (0.005 сек.)