C# Generics bug ? : Delegate can be used as Type in Generic Dictionary

B

Bill Woodruff

<
note : this message was sparked in part by comments by David Browne on a
previous thread : "inserting an anonymous method as a value in a generic
dictionary ?" : David had shown the use of 'Delegate as a valid Type
declaration for the Value of a Generic Dictionary.
I am curious as to why I can compile and use this syntax : it seems to me to
violate the requirement that the Value of a Generic Dictionary be a Type
Name.

private delegate void theHandler();

private Dictionary<Control, theHandler> typeDict;

typeDict = new Dictionary<Control, theHandler>();

I now have a dictonary where the Key is of Type Control, and the Value of
the Key can be a named instance of theHandler :

theHandler theHandler1 = new theHandler(delegate {
MessageBox.Show("hello"); });

TreeView treeView1 = new TreeView();

typeDict.Add(treeView1, theHandler1);

typeDict[treeView1].DynamicInvoke();

Or I could can use an anonymous procedure inserted as a Value :

typeDict.Add
(
treeView1,
delegate
{
TreeNode currentNode = tv1.SelectedNode;
MessageBox.Show("treeview" + " " + currentNode.Text);
}
);
 
M

Marc Gravell

Not sure what the problem is here... what did you expect? theHandler *is* a
type name (declaration); it is a class that derives from MulticaseDelegate
which derives from Delegate which derives from Object. I happily use
delegates in typed collections - on those occasions where I want a
collection of typed delegates!

What is the issue? Sorry if I have missed the point...

Marc

Bill Woodruff said:
<
note : this message was sparked in part by comments by David Browne on
a previous thread : "inserting an anonymous method as a value in a generic
dictionary ?" : David had shown the use of 'Delegate as a valid Type
declaration for the Value of a Generic Dictionary.
I am curious as to why I can compile and use this syntax : it seems to me
to violate the requirement that the Value of a Generic Dictionary be a
Type Name.

private delegate void theHandler();

private Dictionary<Control, theHandler> typeDict;

typeDict = new Dictionary<Control, theHandler>();

I now have a dictonary where the Key is of Type Control, and the Value of
the Key can be a named instance of theHandler :

theHandler theHandler1 = new theHandler(delegate {
MessageBox.Show("hello"); });

TreeView treeView1 = new TreeView();

typeDict.Add(treeView1, theHandler1);

typeDict[treeView1].DynamicInvoke();

Or I could can use an anonymous procedure inserted as a Value :

typeDict.Add
(
treeView1,
delegate
{
TreeNode currentNode = tv1.SelectedNode;
MessageBox.Show("treeview" + " " + currentNode.Text);
}
);
 
B

Bill Woodruff

:
Not sure what the problem is here... what did you expect? theHandler *is*
a type name (declaration); it is a class that derives from
MulticaseDelegate which derives from Delegate which derives from Object. I
happily use delegates in typed collections - on those occasions where I
want a collection of typed delegates!

What is the issue? Sorry if I have missed the point...

.... original post by bw snipped for brevity ...

Marc, thanks for your response ! I posted this example because I was
puzzled by being able to do things this way.

I had always thought of a Delegate as a being more the declaration of a
"signature" of a future Method, rather than as a first-class Type.

While a declaration of the form :

Dictionary<Delegate, Object> theDictionary = new
Dictionary<Delegate, Object>();

Would have still raised questions in my mind, but would have been easily
acceptable, being able to do :

private delegate void theMethodBody;

Dictionary<theMethodBody, Object> theDictionary = new
Dictionary<theMethodBody, Object>();

Somehow seems intutively wrong. So I am just asking for some help in
understanding why this works.

As, so often, the problem being in my assumptions.

thanks, Bill Woodruff
 
M

Marc Gravell

I had always thought of a Delegate as a being more the declaration of a
"signature" of a future Method, rather than as a first-class Type.

It is both.
So I am just asking for some help in understanding why this works.

Actually, Dictionary<theMethodBody, Object> would be a poor choice, as I'm
not sure how useful a delegate would be as a key, but that's irrelvant...
OK; "theMethodBody" here is the signature, but it also defines a type, with
an .Invoke method matching the signature provided by your
delegate-declaration. The key here is getting your head around
"theMethodBody" actually being a class declaration, similar to (not
correct):

public class theMethodBody : MulticastDelegate {
public Invoke(); // matches declares signature; note also Begin/End Invoke
// ctor is a little different to normal, so not included
}

Thus theMethodBody inherits all the features of MulticastDelegate, such as
GetInvocationList(), plus all those features of Delegate such as the
non-typesafe DynamicInvoke(); however, if you know you have a theMethodBody
instance you can use the type-safe Invoke(). All this is done at compile
time.

(As it happens, "theMethodBody" could be substituted for ThreadStart,
MethodInvoker, etc - as these match on signature. )

At runtime, we can create an instance of "theMethodBody"; as with .Net
generally, this delegate-instance is an object instance:
theMethodBody runMe = new theMethodBody(SomeSuitableMethod);
As you know, I can then invoke this either as runMe(), or runMe.Invoke();

Now suppose I want to run a number of methods (with equal signature) based
on the action a user has performed; then yes, I could have some uber-switch
statement, or I could use a Dictionary of typed-delegates:
Dictionary<int, theMethodBody> actions = new Dictionary<int,
theMethodBody>();
// fill
//blah
// user has selected an option; execute the matching code:
actions[selectedActionIndex].Invoke(); // lazy; no checking for existance
etc

It all "just works"; you could use a similar strategy to craft a bespoke
back-end storage for an event mechanism instead of a delegate instance with
+= and -= (although I'm at a loss for a good reason to do so). If this isn't
helping, I suggest reading up on delegates on MSDN.

Marc
 
A

Adam Clauss

Marc Gravell said:
It is both.

One way that might make it "look" better - since "theMethodBody" is acting as a type here, capitalize it:
TheMethodBody

Just a style thing, but it would help fit the concept.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top