C #: менее уродливый синтаксис для создания списков делегатов? - PullRequest
4 голосов
/ 11 декабря 2010

Я строю систему, похожую на LINQ, и при этом пытаюсь поддерживать полиморфные списки обработчиков обратного вызова, и сталкиваюсь с несколькими видами проблем.Короткий способ задать мой вопрос - просто показать код.Моя новая система поддерживает «Группы», и у групп есть вектор точек входа (ниже, UPDATE и CHECKPT), и каждый элемент вектора представляет собой полиморфный список делегатов, который я буду вызывать с помощью отражения.

Итак, пример кода:

namespace ConsoleApplication1
{

    internal delegate void GroupISDHandler(int i, string s, double d);
    class Group
    {
        public class myHandlers {
            internal List<Delegate> hList = new List<Delegate>();
            public static myHandlers operator +(myHandlers a, Delegate b) {
                a.hList.Add(b);
                return a;
            }
        }

        public class mimicVector {
            public List<myHandlers> ListofhLists = new List<myHandlers>();
            public myHandlers this[int i] { get { return ListofhLists[i]; } set { ListofhLists[i] = value; } }
        }

        public mimicVector handlers = new mimicVector();

        public Group(string name) { ... }
    }

    class Program
    {
        internal const int UPDATE = 0;
        internal const int CHECKPT = 1;

        public static void Main()
        {
            Group g = new Group("group name");
            g.handlers[UPDATE] += (GroupISDHandler)delegate(int x, string s, double d) {
                Console.WriteLine("my int,string,double handler was called, with x = {0}, s = {1}, d = {2}", 
                     x,s,d);
            };
        }
    }
}

Мои вопросы центрируются на линии регистрации.Почему C # не может вывести типы, чтобы я мог полностью опустить приведение и новый тип делегата?Я думаю, что из

 g.handlers[UPDATE] += delegate(int x, string s, double d) {
     Console.WriteLine(....);
 };

C # можно вывести необходимую сигнатуру типа.Delegate () будет своего рода анонимным типом, а C # просто сгенерирует что-то вроде

private delegate void _atype1(int _a0, string _a1, double _a2)

, а затем вставит (Delegate)(_atype1) перед компиляцией строки.Таким образом, моему пользователю не нужно объявлять тип делегата (который в настоящее время заставляет ее дважды вводить список аргументов, по сути).

У меня есть System.Linq, так как я на VS 2010. Так что еслиLINQ может каким-то образом вывести нужные броски ...

Ответы [ 2 ]

2 голосов
/ 11 декабря 2010

Вы должны быть в состоянии сделать это следующим образом:

g.handlers[UPDATE] += (GroupISDHandler)((x, s, d) => Console.WriteLine( "my int,string,double handler was called, with x = {0}, s = {1}, d = {2}", x, s, d));

другой вариант будет:

иметь класс с именем ´Parameters ', который является контейнеромдля всего, что пользователь может отправить, могут быть определены типы, если они никогда не изменятся, или список объектов, если вы притворяетесь, что отправляете и получаете различное количество параметров.Затем вместо делегата вы выполняете действие, равное делегату с одним аргументом, и вы можете выполнять вызов без приведения, например:

p => Console.WriteLine ("x = {0},s = {1}, d = {2} ", px, ps, pd);

0 голосов
/ 02 января 2012

Оказывается, что ответ в основном таков: хотя вы можете сделать вывод в тех ситуациях, которые я имел в виду, владельцы C # хотят полностью общих решений, а полиморфизм делает проблему вывода типов слишком сложной для решения в достаточно общем Кстати, по их мнению. Я сам не согласен, поскольку в итоге я дважды набираю все свои подписи, но это их аргументация.

...