Как использовать коллекцию для хранения делегата? - PullRequest
3 голосов
/ 17 сентября 2009

Я хотел иметь хеш-таблицу со строкой в ​​качестве ключа и указатель функции (делегат) в качестве значения. Таким образом, вызывая правильную подпрограмму с помощью строковой команды. Тем не менее, компилятор не будет есть это.

Что я делаю не так?

//declaration
     public delegate void categoryHandler(String request);     

//init code
     Hashtable categories = new Hashtable();
     categories.Add("campaigns", Campaigns.post);

//function call
     String category = "campaigns";
     categoryHandler handler = (categoryHandler) categories[category];
     if (handler != null)
     {
          handler(someString);
     }

//handler
     static public void post(String request)
     {
          ...
     }

Ошибка, которую я получаю, находится в строке, где я помещаю функцию в хеш-таблицу: Ошибка 2 Аргумент «2»: невозможно преобразовать из «группы методов» в «объект»

Я надеюсь, что это просто какая-то семантическая штука, которую я забыл ... Но если это не может быть сделано ... есть ли другой способ создать какую-нибудь таблицу на основе строк?

Ответы [ 4 ]

8 голосов
/ 17 сентября 2009

Проблема в том, что вы используете Hashtable, который имеет слабый тип. Компилятор видит группу методов (имя метода, который вы хотите преобразовать в делегат), но не знает, какой тип делегата вы имеете в виду.

Если вы хотите продолжать использовать Hashtable, вы можете сделать:

categoryHandler handler = Campaigns.post;
categories.Add("campaigns", handler);

или

categories.Add("campaigns", new categoryHandler(Campaigns.post));

В обоих случаях группа методов преобразуется в определенный тип делегата, так что все в порядке.

Тем не менее, лучшим решением является использование Dictionary<string, categoryHandler>, во-первых, всегда используйте строго типизированные коллекции, где вы можете делать это разумно (что почти всегда). Для удобства, это должно быть CategoryHandler btw - это имя типа. Аналогично post должно быть Post.

Затем, чтобы позвонить, вы должны использовать:

 String category = "campaigns";
 CategoryHandler handler;
 if (categories.TryGetValue(category, out handler))
 {
     handler(someString);
 }
2 голосов
/ 17 сентября 2009

Если вы используете .Net 3.5, вы можете делать то, что я делаю, когда я хочу исключить операторы переключения:

private readonly Dictionary<string, Action<string>> _lookupTable = new Dictionary<string, Action<string>>
{
    {"campaigns", post}
    {"somethingElse", doSomethingElse}
    {"tryIt", val => doSomethingWithVal(val)} 
};

тогда, где у меня будет оператор switch, я сделаю это:

_lookupTable["foo"]("bar");
1 голос
/ 17 сентября 2009

Не используйте хеш-таблицу, используйте словарь

Ваш код тоже изменится.

//declaration
     public delegate void categoryHandler(String request);     

//init code
     Dictionary<string, categoryHandler> categories = new Dictionary<string, categoryHandler> ;
     categories.Add("campaigns", Campaigns.post);

//function call
     string category = "campaigns";

     if (!categories.ContainsKey(category))
     {
        // Key not there just return
        return;
     }

     categoryHandler handler = categories[category];  // NO need to cast here

     if (handler != null)
     {
          handler(someString);
     }

//handler
     static public void post(String request)
     {
          ...
     }
0 голосов
/ 17 сентября 2009

В зависимости от используемой версии C # может потребоваться:

categories.Add("campaigns", new categoryHandler(Campaigns.post));

Кроме того, если вы используете .NET 2.0 или выше, вы должны использовать общий класс Dictionary<T,T> вместо Hashtable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...