АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

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

Читайте также:
  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()); } }}

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


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |


Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.005 сек.)