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

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

04.09.2017, 19:24. Показов 3728. Ответов 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
04.09.2017, 21:33
Что-то как-то мудрёно. Может вам такое надо?

C#
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
class A
{
    public void Func(Action<int, int> handler, int x, int y)
    {
        handler(x, y);
    }
}
 
class B
{
    public static void Plus(int x, int y)
    {
        Console.WriteLine($"{x}+{y}={x + y}");
    }
    
    public static void Mul(int x, int y)
    {
        Console.WriteLine($"{x}x{y}={x * y}");
    }
}
 
void Main()
{
    Action<int, int> d = null;
    d += B.Plus;
    d += B.Mul;
    
    new A().Func(d, 3, 8);
}
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
04.09.2017, 21:40  [ТС]
TopLayer, Ну не совсем. Дело в том, что у меня что-то наподобии системы событий. Есть словарь, который хранит делегаты. И вот как раз ключем я хотел сделать тип делегата. Ну в принципе, я понял, что на C#, то, что я хочу сделать - нереально
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
04.09.2017, 22:03
Цитата Сообщение от Bretbas Посмотреть сообщение
Есть словарь, который хранит делегаты.
Что-то такое?
C#
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
delegate void DelegateA();
delegate int DelegateB(float x);
delegate void DelegateC(int x, int y);
 
class Functions
{
    public static void FuncA()
    {
        Console.WriteLine("A");
    }
    
    public static int FuncB(float x)
    {
        Console.Write($"B({x})");
        return 7;
    }
    
    public static void FuncC(int x, int y)
    {
        Console.WriteLine($"C({x}, {y})");
    }
}
 
class Program
{
    public static void Main()
    {
        var dict = new Dictionary<Type, Delegate>();
        dict.Add(typeof(DelegateA), new DelegateA(Functions.FuncA));
        dict.Add(typeof(DelegateB), new DelegateB(Functions.FuncB));
        dict.Add(typeof(DelegateC), new DelegateB(Functions.FuncC));
 
        dict[typeof(DelegateB)].DynamicInvoke(new object[] { 5.7f });
    }
}
Только тут желательно сделать обёртку над словарём, чтобы проверять, что добавляемый ключ действительно является типом-делегатом, а добавляемое значение является экземпляром этого типа-делегата.
1
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
05.09.2017, 05:22
Цитата Сообщение от Bretbas Посмотреть сообщение
Есть словарь, который хранит делегаты. И вот как раз ключем я хотел сделать тип делегата.
Есть готовый словарь делегатов.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 08:43  [ТС]
TopLayer, то что нужно! но долго работает это все как-то долго...

Добавлено через 21 минуту
Вот написал:
C#
1
2
3
4
5
6
7
public void subscribeEvent<T>( Action handler )
{
    if( Events.ContainsKey( typeof(T) ) )
        Events[typeof(T)] = (Action)Events[typeof(T)] + handler;
    else
        Events.Add( typeof(T), handler );
}
Тут одна проблема возникает. Я в параметре кидаю Action, чтобы воспользоваться такой конструкцией подписывания Events[typeof(T)] = (Action)Events[typeof(T)] + handler;. Но проблема в том, что мне придется перегружать метод subscribeEvent для разных типов параметров, тоесть для Action, Action<T>, Action<T, U> и тд. Если я буду передавать не Action, а Delegate к примеру, то оператор + не перегружен для него. У меня выбор только с Action, но там еще ограничения на 16 параметров...

Добавлено через 12 минут
Нет, я могу сделать конечно вот так:
C#
1
2
3
4
5
6
7
public void subscribeEvent<T>( Delegate handler )
{
    if( Events.ContainsKey( typeof(T) ) )
        Events[typeof(T)] = Delegate.Combine( Events[typeof(T)], handler );
    else
        Events.Add( typeof(T), handler );
}
Но тогда при вызове этого метода, мне не получится воспользоваться групповым преобразованием методов, и передавать мне нужно делегат:
C#
1
2
3
4
5
6
7
8
9
...
public static void OnPrintTankId( Tank tank )
{
    Console.WriteLine( tank.Id );
}
...
EventManager.Instance.subscribeEvent<EVENT_TANK_SHOOT>( new EVENT_TANK_SHOOT( OnPrintTankId ));
EventManager.Instance.subscribeEvent<EVENT_TANK_SHOOT>( OnPrintTankId  ); // Вот так не работает
...
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 10:25
Цитата Сообщение от Bretbas Посмотреть сообщение
то оператор + не перегружен для него.
Используйте Delegate.Combine. Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
Delegate main;
 
void Subscribe(Delegate action)
{
    main = Delegate.Combine(main, action);
}
 
void Main()
{
    Subscribe(new Action(() => { Console.WriteLine("AAA"); }));
    Subscribe(new Action(() => { Console.WriteLine("BBB"); }));
    main.DynamicInvoke(new object[] {});
}
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 18:03  [ТС]
TopLayer, Так и сделал Спасибо

Теперь еще один вопрос. Чем разница между DynamicInvoke и просто Invoke/перегруженным ()? Я так понимаю в скорости?
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 18:45
Цитата Сообщение от Bretbas Посмотреть сообщение
Чем разница между DynamicInvoke и просто Invoke/перегруженным ()?
https://stackoverflow.com/ques... amicinvoke

Добавлено через 16 минут
А вот тут предлагается способ ускорить вызов: https://habrahabr.ru/post/279367/#optdelegat
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 19:47  [ТС]
TopLayer, вообщем он медленный. Причем сильно медленный. Я думаю он построен на фоне рефлексии.

Цитата Сообщение от TopLayer Посмотреть сообщение
А вот тут предлагается способ ускорить вызов: https://habrahabr.ru/post/279367/#optdelegat
Да, там предлагается через просмотр количества переданных аргументов вызывать делегат, и если подходящего нет, то по дефолту вызываем DynamicInvoke:
C#
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
internal static object FastDynamicInvokeDelegate(Delegate del, params dynamic[] args)
{
    dynamic tDel = del;
    switch (args.Length)
    {
        default:
            try
            {
                return del.DynamicInvoke(args);
            }
            catch (TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
    #region Optimization
    case 1:
        return tDel(args[0]);
    case 2:
        return tDel(args[0], args[1]);
    case 3:
        return tDel(args[0], args[1], args[2]);
    case 4:
        return tDel(args[0], args[1], args[2], args[3]);
    case 5:
        return tDel(args[0], args[1], args[2], args[3], args[4]);
    case 6:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5]);
    case 7:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
    case 8:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
    case 9:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
    case 10:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
    case 11:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]);
    case 12:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]);
    case 13:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12]);
    case 14:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13]);
    case 15:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14]);
    case 16:
        return tDel(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11], args[12], args[13], args[14], args[15]);
        #endregion
    }
}
С таким же успехом можно было тогда перегружать метод вызова с разными Action, Action<T>, Action<T, U> и так до 16 параметров, которые он поддерживает.

Я в C# новичок, если не сложно, взгляните на мой код, чтобы Вы добавили, что убрали бы?
C#
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
public class EventManager
{
    private EventManager()
    {
    }
 
    // Fields
    private SortedDictionary<Type, Delegate>    events  = new SortedDictionary<Type, Delegate>();
    private static readonly Lazy<EventManager>  lazy    = new Lazy<EventManager>( () => new EventManager(), true );
 
    // Properties
    public static EventManager Instance { get { return lazy.Value; } }
 
    // Methods
    public void SubscribeEvent<T>( Delegate handler )
    {
        Type key = typeof( T );
        if( events.ContainsKey( key ) )
            events[key] = Delegate.Combine( events[key], handler );
        else
            events.Add( key, handler );
    }
    public void UnsubscribeEvent<T>( Delegate handler )
    {
        Type key = typeof( T );
        if( events.ContainsKey( key ) )
            events[key] = Delegate.Remove( events[key], handler );
    }
    public void InvokeEvent<T>( params object[] args )
    {
        Type key = typeof( T );
        if( events.ContainsKey( key ) )
            (events[key]).DynamicInvoke( args );
    }
}
Хотел сделать у SubscribeEvent, UnsubscribeEvent, InvokeEvent ограничение на тип T, что-то вроде такого where T : Delegate, но он ругается на Delegate и не дает мне так сделать

Добавлено через 39 минут
Мой код не работал, не получалось в SortedDictionary хранить два разных ключа Type. Почему, не понятно. Пришлось сделать вот так:
C#
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
public class EventManager
{
    private EventManager()
    {
    }
 
    // Fields
    private SortedDictionary<int, Delegate> events      = new SortedDictionary<int, Delegate>();
    private static readonly Lazy<EventManager>  lazy    = new Lazy<EventManager>( () => new EventManager(), true );
 
    // Properties
    public static EventManager Instance { get { return lazy.Value; } }
 
    // Methods
    public void SubscribeEvent<T>( Delegate handler )
    {
        Type type = typeof( T );
        int key = type.FullName.GetHashCode();
        if( events.ContainsKey( key ) )
            events[key] = Delegate.Combine( events[key], handler );
        else
            events.Add( key, handler );
    }
    public void UnsubscribeEvent<T>( Delegate handler )
    {
        Type type = typeof( T );
        int key = type.FullName.GetHashCode();
        if( events.ContainsKey( key ) )
            events[key] = Delegate.Remove( events[key], handler );
    }
    public void InvokeEvent<T>( params object[] args )
    {
        Type type = typeof( T );
        int key = type.FullName.GetHashCode();
        if( events.ContainsKey( key ) )
            (events[key]).DynamicInvoke( args );
    }
}
Но все равно не получается воспользоваться групповым преобразованием методов:
C#
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
class Program
{
    public delegate void EVENT_TANK_SHOOT( Tank tank );
    public delegate void EVENT_TANK_DIE( Tank tank, string message );
    static void Main(string[] args)
    {   
        EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( new EVENT_TANK_SHOOT( OnPrintTankName ) );
        EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( new EVENT_TANK_SHOOT( OnSound ) );
 
        EventManager.Instance.SubscribeEvent<EVENT_TANK_DIE>( new EVENT_TANK_DIE( OnPrintId ) );
 
        Tank tank = new Tank( "BretbasTank", 1 );
        Tank tank2 = new Tank( "CompTank", 2 );
 
        ConsoleKeyInfo c = new ConsoleKeyInfo();
        while( c.Key != ConsoleKey.Escape )
        {
            c = Console.ReadKey();
            switch( c.Key )
            {
                case ConsoleKey.W:
                    EventManager.Instance.InvokeEvent<EVENT_TANK_SHOOT>( tank );
                break;
                case ConsoleKey.S:
                    EventManager.Instance.InvokeEvent<EVENT_TANK_SHOOT>( tank2 );
                break;
                case ConsoleKey.A:
                    EventManager.Instance.InvokeEvent<EVENT_TANK_DIE>( tank, "Tank is dead. Id of the tank: {0}" );
                break;
            }
        }
 
        Console.ReadLine();
    }
    public static void OnSound( Tank tank )
    {
        Console.Beep();
    }
    public static void OnPrintTankName( Tank tank )
    {
        Console.WriteLine( "Tank name is: {0}", tank.Name );
    }       
    public static void OnPrintId( Tank tank, string message )
    {
        Console.WriteLine( message, tank.Id );
    }           
}
Вот тут хотелось бы писать не вот так:
C#
1
2
3
4
5
6
...
EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( new EVENT_TANK_SHOOT( OnPrintTankName ) );
EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( new EVENT_TANK_SHOOT( OnSound ) );
 
EventManager.Instance.SubscribeEvent<EVENT_TANK_DIE>( new EVENT_TANK_DIE( OnPrintId ) );
...
а вот так:
C#
1
2
3
4
5
6
...
EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( OnPrintTankName );
EventManager.Instance.SubscribeEvent<EVENT_TANK_SHOOT>( OnSound );
 
EventManager.Instance.SubscribeEvent<EVENT_TANK_DIE>( OnPrintId );
...
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 19:59
Цитата Сообщение от Bretbas Посмотреть сообщение
Мой код не работал, не получалось в SortedDictionary хранить два разных ключа Type.
Почему вы пользуетесь SortedDictionary вместо Dictionary?
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 20:14  [ТС]
TopLayer,
Цитата Сообщение от TopLayer Посмотреть сообщение
Почему вы пользуетесь SortedDictionary вместо Dictionary?
Просто смотрю его возможности Это чисто учебный проект

Добавлено через 12 минут
конечно же мне сортировка по ключу в данной задачи не интересует
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 20:17
Лучший ответ Сообщение было отмечено Bretbas как решение

Решение

Цитата Сообщение от Bretbas Посмотреть сообщение
Просто смотрю его возможности
У него есть потребность сортировать ключи, но он не может сравнивать экземпляры типа System.Type
Цитата Сообщение от Bretbas Посмотреть сообщение
а вот так
Могу предложить такое:
C#
1
2
3
4
5
6
7
8
9
    public void SubscribeEvent<T>(T handler)
    {
        var del = (Delegate)(object)handler;
        Type key = typeof(T);
        if (events.ContainsKey(key))
            events[key] = Delegate.Combine(events[key], del);
        else
            events.Add(key, del);
    }
Вызов:
C#
1
EventManager.Instance.SubscribeEvent( (EVENT_TANK_SHOOT)OnPrintTankName )
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 20:23  [ТС]
TopLayer,
Цитата Сообщение от TopLayer Посмотреть сообщение
У него есть потребность сортировать ключи, но он не может сравнивать экземпляры типа System.Type
А Dictionary умеет сравнивать System.Type?

А можете объяснить что это за приведение такое интересное var del = (Delegate)(object)handler;?
0
907 / 664 / 318
Регистрация: 23.10.2016
Сообщений: 1,543
05.09.2017, 20:33
Цитата Сообщение от Bretbas Посмотреть сообщение
А Dictionary умеет сравнивать System.Type?
Любые объекты могут быть проверены на равенство. Но SortedDictionary пытается ещё применить к ним отношения больше-меньше.

Добавлено через 3 минуты
Цитата Сообщение от Bretbas Посмотреть сообщение
А можете объяснить что это за приведение такое интересное var del = (Delegate)(object)handler;?
Привел к типу object, а затем к Delegate. Компилятор не позволяет сразу к Delegate(да и к другим типам) приводить обобщённый тип.
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 20:39  [ТС]
TopLayer,
Цитата Сообщение от TopLayer Посмотреть сообщение
Любые объекты могут быть проверены на равенство. Но SortedDictionary пытается ещё применить к ним отношения больше-меньше.
Ага, понятно. У Dictionary там внутри как раз равенство идет, поэтому можно.

Цитата Сообщение от TopLayer Посмотреть сообщение
Привел к типу object, а затем к Delegate. Компилятор не позволяет сразу к Delegate(да и к другим типам) приводить обобщённый тип.
Вот это самая глобальная проблема в C#. То, к чему я никак не могу привыкнуть после шаблонов C++.
Вы мне можете ответить на вопрос, почему нельзя так делать:
C#
1
2
3
4
public void SubscribeEvent<T>(T handler) where T : Delegate
{
...
}
Компилятор ругается на Delegate. В C# есть ограничения по типу? Вроде я читал есть. И если я делаю ограничение на тип Delegate параметра T, то T может быть или Delegate или наследники Delegate. Почему же компилятор говорит, что так нельзя?
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
05.09.2017, 20:56
Цитата Сообщение от Bretbas Посмотреть сообщение
Вы мне можете ответить на вопрос, почему нельзя так делать:
Можно сделать так:
C#
1
2
3
4
5
6
7
   public static class DelegateHelper
   {
      public static void SubscribeEvent(this Delegate handler)
      {
 
      }
   }
0
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 20:57  [ТС]
Fleder, а как это относится к моей задаче?
0
 Аватар для Fleder
263 / 224 / 108
Регистрация: 09.12.2015
Сообщений: 652
05.09.2017, 21:10
Bretbas, ну, мне показалось, что это можно заюзать в вашем случае.
А вообще, если вы хотите указать в качестве ограничения типа именно Delegate, то так:
C#
1
2
3
4
5
      public void SubscribeEvent<T, D>(T handler) where T : D
      {
      }
      Action action = null;
      SubscribeEvent<Action, Delegate>(action);
1
Каждому свое
 Аватар для Bretbas
533 / 219 / 81
Регистрация: 05.08.2013
Сообщений: 1,614
05.09.2017, 21:18  [ТС]
Еще хотел задать вопрос. Вот у меня метод:
C#
1
2
3
4
5
6
public void InvokeEvent<T>( params object[] args )
{
    Type key = typeof( T );
    if( events.ContainsKey( key ) )
        (events[key]).DynamicInvoke( args );
}
Как должен быть результат этого метода, если пользователь в параметре T передаст тип события, которого нет в словаре? В коде выше ничего при такой ситуации не происходит. Но я думаю, что нужно кинуть исключение. Так вот как лучше его кинуть?
Вот так:
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 );
    }
}
Или еще есть какие способы. Мне нужен именно правильный способ.

Добавлено через 2 минуты
Fleder,
А вообще, если вы хотите указать в качестве ограничения типа именно Delegate, то так:
C#
1
2
3
4
5
      public void SubscribeEvent<T, D>(T handler) where T : D
      {
      }
      Action action = null;
      SubscribeEvent<Action, Delegate>(action);
Можно Но не очень красиво. Спасибо
Так мне не ответили, почему нельзя where T : Delegate? Любой другой тип можно, а этот именно нельзя
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.09.2017, 21:18
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru