Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614

Передача делегата в обобщенную функцию

04.09.2017, 19:24. Показов 3886. Ответов 26
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, Господа. Потихоньку изучаю делегаты.
Не могу понять, как реализовать вот такую вещь:
C#
1
2
3
4
5
6
7
class A
{
    public void Func<T>( MulticastDelegate handler, int x, int y )
    {
        (T)handler( x, y );
    }
}
Тоесть есть класс A, там есть открытая шаблонная функция, которая принимает 3 параметра - делегат, и 2 параметра вызова делегата.
Я хочу при вызове этой функции, передавать делегат( как я понял, все делегаты являются наследниками MulticastDelegate ), который выглядеть будет примерно так: void delegate MyDelegate( int x, int y ), что соответствует вызову внутри функции Func. Параметр обобщения буду передавать тип MyDelegate, чтобы правильно привести его внутри.
Вообщем вызов должен быть таким:
C#
1
2
3
4
void delegate MyDelegate( int x, int y );
MyDelegate d;
... // тут подписываюсь
Func<MyDelegate>( d, 4, 3 );
У меня выдает ошибки на все что только можно... помогите разобраться...я пришел к Вам из простор C++, там что-то вроде такого реализовывается на ура...а здесь...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.09.2017, 19:24
Ответы с готовыми решениями:

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

Составить обобщенную функцию Лагранжа
Здравствуйте, как реализовать данный алгоритм. Есть пример разобранный по этому алгоритму

Вывести и записать обобщенную функцию для вычисления значения X,Y,Z
Помогите пожалуйста решить попроще. Спасибо большое заранее. Первое-значение Х, второе-Y,третье-Z п. 5.18 Правил Запрещено размещать...

26
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 23:11
Студворк — интернет-сервис помощи студентам
Я вот подумал: а зачем тут вообще дженерик?
Можно же в таком духе:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class EventManager
{
    private Dictionary<Type, Delegate> _handlers = new Dictionary<System.Type, System.Delegate>();
    
    public void Sub(Delegate handler)
    {
        if (handler == null) throw new ArgumentNullException(nameof(handler));
        
        Type handlerType = handler.GetType();
        Delegate prevHandler;
        
        if (_handlers.TryGetValue(handler.GetType(), out prevHandler))
        {
            _handlers[handlerType] = Delegate.Combine(prevHandler, handler);
            return;
        }
        
        _handlers.Add(handlerType, handler);
    }
}
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
06.09.2017, 07:57  [ТС]
TopLayer, Можно и так. Я тоже думал об этом. А вызов InvokeEvent все равно должна быть обобщенная же? Уже так не прокатит как с Sub/SubscribeEvent...

Вы не знаете почему нельзя ограничивать тип T до Delegate? Тоесть where T : Delegate. Почему-то мой вопрос игнорят

И как лучше исключения пускать? Так:
C#
1
2
3
4
5
6
7
8
9
public class EventNotFoundException : ApplicationException { ... }
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    if( events.ContainsKey( key ) )
        (events[key]).DynamicInvoke( args );
    else
        throw new EventNotFoundException( "Вызываемое событие не было найдена в менеджере" );
}
или так:
C#
1
2
3
4
5
6
7
8
9
10
public class EventNotFoundException : ApplicationException { ... }
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    try {(events[key]).DynamicInvoke( args ); }
    catch( KeyNotFoundException e )
    {
        throw new EventNotFoundException( "Вызываемое событие не было найдена в менеджере", e );
    }
}
или еще как-то?
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
06.09.2017, 09:08
Лучший ответ Сообщение было отмечено Bretbas как решение

Решение

Цитата Сообщение от Bretbas Посмотреть сообщение
Вы не знаете почему нельзя ограничивать тип T до Delegate? Тоесть where T : Delegate. Почему-то мой вопрос игнорят
В реализации .NET от Microsoft существует запрет на использование специальных классов, таких как:
System.Object, System.Array, System.Delegate, System.Enum, System.ValueType
в качестве ограничения на базовый класс для дженериков.

Это ошибка компиляции CS0702. Не совсем понятно, почему так сделали, особенно учитывая тот факт,
что на неприкрытое ограничение на базовый класс эта ошибка не распространяется:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
      //так нельзя (ошибка CS0702)
      public void SubscribeEvent<T>(T handler) where T : Delegate
      {
      }
 
      //а так можно (используется неприкрытое ограничение)
      public void SubscribeEvent<T, U>(T handler) where T : U
      {
      }
      private void Foo()
      {
         Action handler = null;
         SubscribeEvent<Action, Delegate>(handler);
      }
Добавлено через 12 минут
Цитата Сообщение от Bretbas Посмотреть сообщение
И как лучше исключения пускать?
Есть ещё такой вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
12
      public class EventNotFoundException : ApplicationException { ... }
      public void InvokeEvent<T>(params object[] args)
      {
         if(events.TryGetValue(typeof(T), out Delegate value))
         {
            value.DynamicInvoke(args);
         }
         else
         {
            throw new EventNotFoundException("Вызываемое событие не было найдено в менеджере");
         }
      }
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
06.09.2017, 13:39  [ТС]
Fleder,
В реализации .NET от Microsoft существует запрет на использование специальных классов, таких как:
System.Object, System.Array, System.Delegate, System.Enum, System.ValueType
в качестве ограничения на базовый класс для дженериков.
понятно...

Цитата Сообщение от Fleder Посмотреть сообщение
Есть ещё такой вариант:
C#
1
2
3
4
5
6
7
8
9
10
11
12
      public class EventNotFoundException : ApplicationException { ... }
      public void InvokeEvent<T>(params object[] args)
      {
         if(events.TryGetValue(typeof(T), out Delegate value))
         {
            value.DynamicInvoke(args);
         }
         else
         {
            throw new EventNotFoundException("Вызываемое событие не было найдено в менеджере");
         }
      }
Ну а какой лучше то и правильнее?
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
06.09.2017, 13:54
Цитата Сообщение от Bretbas Посмотреть сообщение
Ну а какой лучше то и правильнее?
C#
1
2
3
4
5
6
7
8
9
public class EventNotFoundException : ApplicationException { ... }
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    if( events.ContainsKey( key ) )
        (events[key]).DynamicInvoke( args );
    else
        throw new EventNotFoundException( "Вызываемое событие не было найдена в менеджере" );
}
В этом варианте мы два раза обращаемся к словарю: сначала проверяем наличие ключа, потом индексируем значение.
Есть в сети рекомендации, что так, типа, лучше не делать, мол, долго (два метода вызываются).




C#
1
2
3
4
5
6
7
8
9
10
public class EventNotFoundException : ApplicationException { ... }
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    try {(events[key]).DynamicInvoke( args ); }
    catch( KeyNotFoundException e )
    {
        throw new EventNotFoundException( "Вызываемое событие не было найдена в менеджере", e );
    }
}
В этом варианте логика построена на исключениях - такую практику крайне не рекомендуют.
Она самая тормозная.




C#
1
2
3
4
5
6
7
8
9
10
11
12
public class EventNotFoundException : ApplicationException { ... }
      public void InvokeEvent<T>(params object[] args)
      {
         if(events.TryGetValue(typeof(T), out var value))
         {
            value.DynamicInvoke(args);
         }
         else
         {
            throw new EventNotFoundException("Вызываемое событие не было найдено в менеджере");
         }
      }
А такой вариант считается самым быстрым. Тут всего одно обращение к словарю.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
06.09.2017, 14:38  [ТС]
Fleder,
C#
1
2
3
4
5
6
7
8
9
10
public class EventNotFoundException : ApplicationException { ... }
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    try {(events[key]).DynamicInvoke( args ); }
    catch( KeyNotFoundException e )
    {
        throw new EventNotFoundException( "Вызываемое событие не было найдена в менеджере", e );
    }
}
В этом варианте логика построена на исключениях - такую практику крайне не рекомендуют.
Она самая тормозная.
Да, но она тормозная только в том случае, если исключение возникнет. Если исключение не возникает в момент вызова этого метода, то вроде это никак не должно повлиять на производительность.

C#
1
2
3
4
5
6
7
8
9
10
11
12
public class EventNotFoundException : ApplicationException { ... }
      public void InvokeEvent<T>(params object[] args)
      {
         if(events.TryGetValue(typeof(T), out var value))
         {
            value.DynamicInvoke(args);
         }
         else
         {
            throw new EventNotFoundException("Вызываемое событие не было найдено в менеджере");
         }
      }
А такой вариант считается самым быстрым. Тут всего одно обращение к словарю.
интересно, что происходит в events.TryGetValue(typeof(T), out var value)?
Если этот вариант самый быстрый, то буду придерживаться его
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
06.09.2017, 14:46
Цитата Сообщение от Bretbas Посмотреть сообщение
интересно, что происходит в events.TryGetValue(typeof(T), out var value)?
Можете посмотреть сами.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.09.2017, 14:46

Сделать обобщенную функцию, которая поворачивает фигуры на заданный угол, описав класс треугольник и квадрат
Сделать обобщенную функцию,которая поворачивает фигуры на заданный угол, описав класс треугольник и квадрат. Хотелось бы получить...

Разница лямбда выражения, делегата (\анонимного делегата), методом (\анонимных методов)
Всё просто: В чём отличия: лямбд, делегатов, анонимных делегатов, методов, анонимных методов? У меня в проге сучилась такая...

Отличие делегата от делегата с лямбда-выражением
Народ чем отличается Invoke(new Action(() =&gt; button2.IsEnabled = true)); от Invoke(new Action(delegate(){ button2.IsEnabled = true;...

Протабулировать произвольную функцию на отрезке a, b с шагом h с использованием делегата
Протабулировать произвольную функцию на отрезке a,b с шагом h с использованием делегата для задания вида табулируемой функции. определить 3...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
Новые блоги и статьи
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru