Delegates are C#'s replacement for C++ pointers-to-(member)-functions. They are declared using a syntax a bit like a C-style function prototype. I tend to type curly bracket languages with a heavy C accent--I've been known to declare the argument of a Java main method as
Object[] argv
. So without thinking about it too much I typed my first ever delegate declaration something like this:delegate void doStuff(object arg);(all names have been changed to protect my employer's IP)
And then a new delegate object can be created, like this
doStuff sd = new doStuff(stuffDoer.doYourThing);Where
stuffDoer
is an instance of a class with a method who's type signature (but not name) matches the type of the delegate. So there's a kind of duck typing for methods going on here.Then,
sd
can be passed into a method declared like this:public void doStuffUsing(stuffDoer doStuffWith){in this way:
doStuffWith(anObject)
}
foo.doStuffUsing(sd);Do you see my problem?
In the C/C++ world there is a desire to make the declaration and use of an identifier as similar as possible. That's why a pointer-to-member-function is declared (and initialized) like this:
void (StuffDoer::*fptr)(void*) = &StuffDoer::doYourThing;and then used like this:
void SomeClass::doStuffUsing(void (StuffDoer::*fptr)(void*)){The C# syntax is clearer and more concise, by a long way, and the delegate has the nice (and safer) feature that it closes over the target object. In fact delegates have a property on them called Target that holds a reference to that object.
StuffDoer sd;
(sd.*fptr)(this.pObject);
}
But the C++ form is more consistent, there's a direct 1:1 relationship between almost all the parts of the declaration, mention and use. The places where there isn't that relationship are marked by the dereference syntax.
Now, the syntax of the declaration of the delegate,
delegate void doStuff(object arg)
does look a lot like a use, like doStuffWith(anObject)
which is cool. But what looks like a method name in the declaration is really the name of the type of delegate object. Thus mentions of the delegate type, such asdoStuff sd = new doStuff(stuffDoer.doYourThing)look a bit fishy to me, for that reason.
So, I thought, maybe it should be
delegate void DoStuff(object arg)
so that creating the delegate looks like a constructor call:DoStuff sd = new DoStuff(stuffDoer.doYourThing);But these don't look right next to each other either, because the parameter to the constructor call is in no way related to what looks like corresponding parameter seen in the delegate declaration. Ouch.
Looking at the MSDN example (often highly dubious as that source can be), it looks to me as if there is anyway a convention in the C# world to name properties and methods with a leading capital anyway, which also looks very odd to me. Not to mention the type
object
being spelled with an "o" not an "O"
No comments:
Post a Comment