C#: Less ugly syntax for creating delegate lists?
I'm building a system a bit like LINQ, and in doing it, am trying to support polymorphic callback handler lists, and am running into several kinds of problems. The short way to ask my question is to just show you some code. My new system supports "Groups" and groups have a vector of entry points (below, UPDATE and CHECKPT) and each element on the vector is a polymorphic list of delegates, which I'll call back using reflection.
So, sample code:
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);
};
}
}
}
My questions centers on the registration line. Why can't C# infer the types so that I could omit the cast and the new delegate type entirely? I would think that from
g.handlers[UPDATE] += delegate(int x, string s, double d) {
Console.WriteLine(....);
};
C# could infer the needed type signature. delegate() would be a kind of anonymous type and C# would just generate something like
private delegate void _atype1(int _a0, string _a1, double _a2)
and then insert (Delegate)(_atype1)
before compiling the line. Thus my user won't need to declare a delegate type (which currently forces her to type the argument list twice, in effect).
I do have System.Linq
since I'm on VS 2010. So if LINQ can somehow i开发者_StackOverflownfer the needed casts...
you should be able to do it this way:
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));
another option would be:
have a class named ´Parameters´ that is a container for whatever the user can send, might be defined types if they never change, or a list of objects if you pretend to send and receive different amount of parameters. Then instead of a Delegate, you would take Action that equals a delegate that takes one argument, and you could do your call without casting like this:
p => Console.WriteLine("x = {0}, s = {1}, d = {2}", p.x, p.s, p.d);
Turns out that the answer is basically this: while you can do the inference in the kinds of situations I had in mind, the C# owners want completely general solutions and polymorphism makes the type inference problem too hard to solve in a sufficiently general way, in their view. I myself disagree since I end up typing all my type signatures twice, but that's their reasoning.
精彩评论