Массив делегатов в C#

Я экспериментирую с вызовом функций делегата из массива делегатов. Мне удалось создать массив делегатов, но как мне вызвать делегата?

public delegate void pd();

public static class MyClass
{

    static void p1()
    {
        //...
    }

    static void p2 ()
    {
        //...
    }

    //...

    static pd[] delegates = new pd[] {

        new pd( MyClass.p1 ),
        new pd( MyClass.p2)
        /* ... */
    };
}

public class MainClass
{
    static void Main()
    {
        // Call pd[0]
        // Call pd[1]
    }
}

EDIT: Причина для массива в том, что мне нужно вызывать функции делегата по индексу по мере необходимости. Они не запускаются в ответ на событие. Я вижу критическую (глупую) ошибку в своем коде, поскольку я пытался выполнить функцию делегата, используя тип pd[], а не имя массива (делегатов).


person pro3carp3    schedule 31.10.2008    source источник


Ответы (4)


Если они все одного типа, почему бы просто не объединить их в один многоадресный делегат?

static pd delegateInstance = new pd(MyClass.p1) + new pd(MyClass.p2) ...;

...
pd();
person Jon Skeet    schedule 31.10.2008
comment
Одной из причин этого не может быть индивидуальная обработка исключений, создаваемых любым из делегатов, а не просто перехват первого. - person Jacob Carpenter; 01.11.2008
comment
Согласно моему редактированию, делегаты не выполняются в ответ на событие, а вызываются индивидуально с использованием индекса в массиве. - person pro3carp3; 01.11.2008
comment
@jacob_c - да, если вы действительно этого хотите :) @pro3carp3 - в этом случае вам просто нужно получить к нему доступ по индексу, как обычно для массива. Здесь нет ничего особенного в том, чтобы быть делегатом. - person Jon Skeet; 01.11.2008
comment
Спасибо, Джон. Я сделал глупую ошибку и подумал, что я что-то упустил. - person pro3carp3; 02.11.2008

В .Net любой делегат фактически является «многоадресным» делегатом (он наследуется от этого встроенного базового класса) и, следовательно, содержит внутренний связанный список, который может содержать любое количество целевых делегатов.

Вы можете получить доступ к этому списку, вызвав метод GetInvocationList() для самого делегата. Этот метод возвращает массив делегатов...

Единственное ограничение состоит в том, что все делегаты внутри связанного списка данного делегата должны иметь одинаковую подпись (относиться к одному и тому же типу делегата). Если вам нужно, чтобы ваша коллекция могла содержать делегатов разных типов, вам нужно создать свой собственный список или класс коллекции.

Но если это нормально, вы можете «вызывать» делегатов в списке вызовов данного делегата следующим образом:

public delegate void MessageArrivedHandler(MessageBase msg);
public class MyClass
{
     public event MessageArrivedHandler MessageArrivedClientHandler;   

     public void CallEachDelegate(MessageBase msg)
     {
          if (MessageArrivedClientHandler == null)
              return;
          Delegate[] clientList = MessageArrivedClientHandler.GetInvocationList();
          foreach (Delegate d in clientList)
          {
              if (d is MessageArrivedHandler)
                  (d as MessageArrivedHandler)(msg);
          }
     }
}
person Charles Bretana    schedule 31.10.2008

person    schedule
comment
Технически это должен быть MyClass.pd[0](). pd — это тип, а MyClass.pd — статический член MyClass. - person Mark Brackett; 01.11.2008
comment
Почему бы вам не объединить les PD вместе! - person Jb Evain; 26.10.2009

person    schedule
comment
Это делегат, а не делегат - person Davide Andrea; 18.01.2016