473,544 Members | 713 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Multicast delegates and hashtable problem

Hello all—

I’m trying to get the below to work and cannot get the format right.

It’s from this example: http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

What it is: I’m trying to store multicast delegates in a hash table,
and then fire the delegates one of two ways (after registering/
creating the delegates, etc).

First, either traversing the entire hash table, using foreach
(Hashtable h in eventTable) logic (see- //does not work-how to make it
work?).

Second, by calling up the value of a hashtable through the key. But
how to cast and fire the delegate? I get the error CS0079, see below.

But manually I can get these delegates to fire (see output at Main
below). However, I want to automate this process (I think that’s the
point behind the link above, though I could be wrong).

Any suggestions even outside of actual code appreciated.

RL

/////////////// works, but not ‘automated’
hi:1
hi:10
Ray
i, object are: 123, !
i, object are: 123, $
i, object areTWO: 123, $
notice chaining of delegates for x3
myFoo4()...noth ing
The End
Press any key to continue . . .

///////////////

using System;
using System.Collecti ons.Generic;
using System.Linq;
using System.Text;

namespace MediatorC
{
class Program
{
static void Main(string[] args)
{
// http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

PropertyEventsS ample myPES = new PropertyEventsS ample();

// manual way - works but not automated

MyDelegate1 x = null;

// x += new MyDelegate1(myP ES.myTest1.myFo o1); //old style
x += myPES.myTest1.m yFoo1;

x(1); //works
x += new MyDelegate1(myP ES.myTest1.myFo o12);
x(10); //works

MyDelegate2 x2 = null;
x2 += new MyDelegate2(myP ES.myTest1.myFo o2);
x2("Ray");

MyDelegate3 x3 = null;
x3 += new MyDelegate3(myP ES.myTest1.myFo o3);
x3(123, '!');
x3 += new MyDelegate3(myP ES.myTest1.myFo o32);
x3(123, '$');

Console.WriteLi ne("notice chaining of delegates for x3");

MyDelegate4 x4 = null;
x4 += new MyDelegate4(myP ES.myTest1.myFo o4);
x4();
// trying to get this to fire...failed
//myPES.Event1 += new MyDelegate1(myP ES.myTest1.myFo o1);
//myPES.Event2 += new MyDelegate1(myP ES.myTest1.myFo o12);
////
//myPES.Event3 += new MyDelegate2(myP ES.myTest1.myFo o2);
////
//myPES.Event4 += new MyDelegate3(myP ES.myTest1.myFo o3);
//myPES.Event5 += new MyDelegate3(myP ES.myTest1.myFo o32);
////
//myPES.Event6 += new MyDelegate4(myP ES.myTest1.myFo o4);

//////////////////////////// failed///
// myPES.FireAway( "Event1");

// myPES.Event1(1) ;

// myPES.Event1.In voke(1);

// myPES.eventTabl e["Event1"]
Console.WriteLi ne("The End");
}
}
}
//////////////////////////////////////////////////
using System;
using System.Collecti ons;
using System.Collecti ons.Generic;
using System.Linq;
using System.Text;

namespace MediatorC
{

public delegate void MyDelegate1(int i);
public delegate void MyDelegate2(str ing s);
public delegate void MyDelegate3(int i, object o);
public delegate void MyDelegate4();

public class Test1
{

public int i;
public string s;
public Test1()
{ i = 0; s = "hi!"; }

public void myFoo1(int i)
{ this.i = i; Console.WriteLi ne("hi:{0}", i); }

public void myFoo12(int i)
{ this.i = 2*i; }

public void myFoo2(string s)
{ this.s = s; Console.WriteLi ne(s); }

public void myFoo3(int i, object o)
{ Console.WriteLi ne("i, object are: {0}, {1}", i, o); }

public void myFoo32(int i, object o)
{ Console.WriteLi ne("i, object areTWO: {0}, {1}", i, o); }

public void myFoo4()
{ Console.WriteLi ne("myFoo4()... nothing"); }
}

public class PropertyEventsS ample
{
//http://msdn.microsoft. com/en-us/library/8627sbea(VS.
71).aspx
public Test1 myTest1;
private Hashtable eventTable;

public PropertyEventsS ample()
{
myTest1 = new Test1();

eventTable = new Hashtable();

Event1 += new MyDelegate1(myT est1.myFoo1);
// eventTable.Add( "Event1", Event1); //improper, does not work

//eventTable.Add( "Event1", Event1); //improper, does not work
//error CS0079 The event
'MediatorC.Prop ertyEventsSampl e.Event1' can only appear on the left
hand side of += or -=

Event2 += new MyDelegate1(myT est1.myFoo12);
//
Event3 += new MyDelegate2(myT est1.myFoo2);
//
Event4 += new MyDelegate3(myT est1.myFoo3);
Event5 += new MyDelegate3(myT est1.myFoo32);
//
Event6 += new MyDelegate4(myT est1.myFoo4);

}

public void FireAway()
{
//if (eventTable[str1] != null)
//{ }
foreach (Hashtable h in eventTable)
{
//h.Values; //does not work-how to make it work?
}
//
}

public event MyDelegate1 Event1
{
add
{
eventTable["Event1"] =
(MyDelegate1)ev entTable["Event1"] + value;
}
remove
{
eventTable["Event1"] =
(MyDelegate1)ev entTable["Event1"] - value;
}
}

public event MyDelegate1 Event2
{
add
{
eventTable["Event2"] =
(MyDelegate1)ev entTable["Event2"] + value;
}
remove
{
eventTable["Event2"] =
(MyDelegate1)ev entTable["Event2"] - value;
}
}

public event MyDelegate2 Event3
{
add
{
eventTable["Event3"] =
(MyDelegate2)ev entTable["Event3"] + value;
}
remove
{
eventTable["Event3"] =
(MyDelegate2)ev entTable["Event3"] - value;
}
}

public event MyDelegate3 Event4
{
add
{
eventTable["Event4"] =
(MyDelegate3)ev entTable["Event4"] + value;
}
remove
{
eventTable["Event4"] =
(MyDelegate3)ev entTable["Event4"] - value;
}
}

public event MyDelegate3 Event5
{
add
{
eventTable["Event5"] =
(MyDelegate3)ev entTable["Event5"] + value;
}
remove
{
eventTable["Event5"] =
(MyDelegate3)ev entTable["Event5"] - value;
}
}

public event MyDelegate4 Event6
{
add
{
eventTable["Event6"] =
(MyDelegate4)ev entTable["Event6"] + value;
}
remove
{
eventTable["Event6"] =
(MyDelegate4)ev entTable["Event6"] - value;
}
}
}
}
///////////////////////////////////////
Oct 10 '08 #1
9 3095
raylopez99 <ra********@yah oo.comwrote:
I=3Fm trying to get the below to work and cannot get the format right.

It=3Fs from this example: http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

What it is: I=3Fm trying to store multicast delegates in a hash table,
and then fire the delegates one of two ways (after registering/
creating the delegates, etc).
Why are you using Hashtable instead of the strongly typed
Dictionary<TKey , TValue>?
First, either traversing the entire hash table, using foreach
(Hashtable h in eventTable) logic (see- //does not work-how to make it
work?).
The hashtable isn't storing hashtables, it's storing key/value pairs
where the key is a string and the value is a delegate. It's not exactly
clear what you're trying to do here.
Second, by calling up the value of a hashtable through the key. But
how to cast and fire the delegate? I get the error CS0079, see below.
You're trying to use an event as if it's a variable. Events just
support add/remove - not fetch. See
http://pobox.com/~skeet/csharp/events.html
But manually I can get these delegates to fire (see output at Main
below). However, I want to automate this process (I think that=3Fs the
point behind the link above, though I could be wrong).

Any suggestions even outside of actual code appreciated.
It's not clear to me which bit is failing for you, partly because your
example is so long. You've commented out lots of code, but lots of that
is okay. *Short* but complete examples are important - although I'm
grateful that the example is at least complete.

If all that's going wrong is going through the hashtable - and if you
really still want to use a hashtable - then you need to cast each value
in the table to the appropriate delegate type and execute it. That's
somewhat tricky in your case, as you've got 4 different signatures -
what do you want the arguments to the delegate invocation to be?

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Oct 10 '08 #2
raylopez99 <ra********@yah oo.comwrote:
Why are you using Hashtable instead of the strongly typed
Dictionary<TKey , TValue>?
Because that was the container in: http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx
That's what you get from reading 5-year-old documentation - but it's
always a good idea to use the generic containers instead of
Hashtable/ArrayList/etc.
BTW, if you care to comment about what exactly is going on in the
above link, please feel free to do so.
Which bit are you puzzled about?
First, either traversing the entire hash table, using foreach
(Hashtable h in eventTable) logic (see- //does not work-how to make it
work?).
The hashtable isn't storing hashtables, it's storing key/value pairs
where the key is a string and the value is a delegate. It's not exactly
clear what you're trying to do here.
I found a solution that does what I am trying to do--at least the
first of the two questions. If you have the book by O'Reilly "C#
Cookbook" by Hilyard and Teilhet, 2nd ed (Updated for C#2.0), look at
chapter 9, receipe 9.1 "Controllin g when and if a delegate fires
within a multicast delegate". They use an array to store various
delegates, rather than a hash table as in my OP, then they traverse
the array using for() logic. They show how you can traverse backwards
and forwards and skip every other delegate, etc, as you can traversing
any array. Basically one of the two questions was this--how to store
disparate delegates in a container and traverse the container. Of
interest is that you can add delegates of disparate signatures,
exactly as I proposed, e.g., for those who don't have the book before
them reading this thread:
Having different types within a container usually leads to more issues
than it solves, IMO...
Second, by calling up the value of a hashtable through the key. *But
how to cast and fire the delegate? *I get the error CS0079, see below.
You're trying to use an event as if it's a variable. Events just
support add/remove - not fetch. Seehttp://pobox.com/~skeet/csharp/events.html
Could not follow.
You were trying to add "Event1" to your hashtable. You can't do that,
because that's an event, not a delegate.
Can you give an example of a cast from a hashtable
(or a dictionary)? Referring to the above example for an array, a
cast would be along the lines of: ((FirstDelegate )
delegateArrayLi st[counter])();

If it's quick to show--don't waste your time please.
foreach (Delegate delegate in hashtable.Keys)
If all that's going wrong is going through the hashtable - and if you
really still want to use a hashtable - then you need to cast each value
in the table to the appropriate delegate type and execute it. That's
somewhat tricky in your case, as you've got 4 different signatures -
what do you want the arguments to the delegate invocation to be?
Aha! A valuable clue "somewhat tricky".
The more valuable clue should be the question of what arguments you
want to pass in.
So perhaps the link by MSDN
above is referring to something else. And perhaps the receipe 9.1 is
the way to go rather than using a hashtable or dictionary...I' ll post
later today if I have time with a solution...
Why are you trying to do this anyway? What's the overall goal? There's
almost certainly a better way of doing it.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Oct 10 '08 #3
On Oct 10, 2:55*am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
raylopez99 <raylope...@yah oo.comwrote:
Why are you using Hashtable instead of the strongly typed
Dictionary<TKey , TValue>?
Because that was the container in:http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

That's what you get from reading 5-year-old documentation - but it's
always a good idea to use the generic containers instead of
Hashtable/ArrayList/etc.
OK, you solved it then. Thanks.

>
BTW, if you care to comment about what exactly is going on in the
above link, please feel free to do so.

Which bit are you puzzled about?

Nothing. It's obsolete, like you say. let's move on, I got some
better stuff (see below).
Having different types within a container usually leads to more issues
than it solves, IMO...
Good. Because I was thinking of using ArrayList (which as you know
can store different types) to store different Delegates (having
different signatures). But you talked me out of it. Now see the
below.
foreach (Delegate delegate in hashtable.Keys)
If all that's going wrong is going through the hashtable - and if you
really still want to use a hashtable - then you need to cast each value
in the table to the appropriate delegate type and execute it. That's
somewhat tricky in your case, as you've got 4 different signatures -
what do you want the arguments to the delegate invocation to be?
Exactly. I'm struggling with this and concluding it's not worth the
hassle. Better to have a 'loop' or container for each delegate, see
below for example with MyDelegate3.

Why are you trying to do this anyway? What's the overall goal? There's
almost certainly a better way of doing it.
No overall goal. I'm trying to see how to use delegates. You can get
a delegate to return an int or a parameter than use it to control
whether you fire other delegates "chained" in an array. This is
Receipe 9.1 in the Cookbook.

Now see this--there's many ways of registering/instantiating/setting
up delegates. Note the way I now handle "MyDelegate 3" below (I've
commented out the way it was done previously). I'm using an array
this time.

Start with the comment //////// equivalent Jon Skeet start here
This also shows how stuff is equivalent.

Then move to "MyDelegate 3" and see how I use an array to fire the two
instances of this delegate. But--and this is key--they are the same
type of delegate (taking an 'int' and an 'object' and returning
'void'). Another key: using the method GetInvocationLi st (see
below).

I've concluded--thanks to this thread--that trying to fit disparate
delegates into a container and then feeding them parameters, etc, is
not worth the cost. Talk me out of it if you may but this is a rule I
will file away for future reference.

I might post later on using a Hashtable in lieu of an array, but
honestly I don't see why that's necessary. The obsolete link
referenced above implied for numerous delegates it's necessary, but I
think for 99% of programs an array as per the below or simple use of
+= chaining should be sufficient.

RL

///////////////////////////////////////////////////////////// OUTPUT,
as before, and as one would expect: /////////////////
hi:1
hi:10
Rays
begin delegate array
i, object are: 1234, @
i, object areTWO: 1234, @
end delegate array
notice chaining of delegates for x3
myFoo4()...noth ing
The End
Press any key to continue . . .
//////////////////////////////////////////////////////////////////////////////////

class Program
{
static void Main(string[] args)
{
// http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

//Mediator m = new Mediator();
//Colleague2 head2 = new Colleague2(m, "lucy", 11, 'l');
//Colleague1 head1 = new Colleague1(m, "john", 10, 'j');

//head1.SendC1(10 ); //colleague1 is even numbers
//head2.SendC1(11 );
//Console.WriteLi ne("Mediator typeof(T).
Module,.Name, .Namespace are- {0}, {1}, {2}", typeof(Mediator ).Module,
typeof(Mediator ).Name, typeof(Mediator ).Namespace);
PropertyEventsS ample myPES = new PropertyEventsS ample();

// manual way
MyDelegate1 x = null;
// x += new MyDelegate1(myP ES.myTest1.myFo o1); //old style
x += myPES.myTest1.m yFoo1;
x(1); //works
x += new MyDelegate1(myP ES.myTest1.myFo o12);
x(10); //works

//////// equivalent Jon Skeet start here

// p. 107 Albahari equivalent: ////////////////
MyDelegate2 x2 = new MyDelegate2(myP ES.myTest1.myFo o2); //
I call this 'new style'
x2("Rays");

// MyDelegate2 x2 = null;
//x2 += new MyDelegate2(myP ES.myTest1.myFo o2); //'old
style' using += operator (equivalent)
//x2("Ray");
///////////////////////////////////////////////

//MyDelegate3 x3 = null;
//x3 += new MyDelegate3(myP ES.myTest1.myFo o3);
//x3(123, '!');
//x3 += new MyDelegate3(myP ES.myTest1.myFo o32);
//x3(123, '$');

MyDelegate3 myDelegate3Inst ance1 = new
MyDelegate3(myP ES.myTest1.myFo o3); //new style,compare with above
MyDelegate3 myDelegate3Inst ance2 = new
MyDelegate3(myP ES.myTest1.myFo o32);

MyDelegate3 allInstances_of _Del3 = myDelegate3Inst ance1 +
myDelegate3Inst ance2; //pretty slick, eh Jon Skeet?

Delegate[] delegateList3 =
allInstances_of _Del3.GetInvoca tionList();
//key, to use .GetInvocationL ist, which returns an array of Delegate
<generic! This is key Jon, the use of the .GetInvocationL ist
extension method

Console.WriteLi ne("begin delegate array");

for (int counter = 0; counter < delegateList3.L ength;
counter++)
{
((MyDelegate3)d elegateList3[counter])(1234,'@'); //
note format for cast

}

Console.WriteLi ne("end delegate array");

// end here Jon Skeet
Console.WriteLi ne("notice chaining of delegates for x3");

MyDelegate4 x4 = null;
x4 += new MyDelegate4(myP ES.myTest1.myFo o4);
x4();
}

Oct 10 '08 #4
On Oct 10, 2:55*am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
>
Why are you trying to do this anyway? What's the overall goal? There's
almost certainly a better way of doing it.

Ok my long reply got lost in the ether. Suffice to say that you've
helped me a lot Jon. I concluded you should not mix delegates (1,2,3,
4 ) in the OP, regardless of container (whether hashtable or array)
and using .GetInvocation extension method helps in an array of
delegates. See MyDelegate3 below. Sorry I had a more complete reply
but it got lost.

RL
class Program
{
static void Main(string[] args)
{
// http://msdn.microsoft.com/en-us/libr...ea(VS.71).aspx

//Mediator m = new Mediator();
//Colleague2 head2 = new Colleague2(m, "lucy", 11, 'l');
//Colleague1 head1 = new Colleague1(m, "john", 10, 'j');

//head1.SendC1(10 ); //colleague1 is even numbers
//head2.SendC1(11 );
//Console.WriteLi ne("Mediator typeof(T).
Module,.Name, .Namespace are- {0}, {1}, {2}", typeof(Mediator ).Module,
typeof(Mediator ).Name, typeof(Mediator ).Namespace);
PropertyEventsS ample myPES = new PropertyEventsS ample();

// manual way
MyDelegate1 x = null;
// x += new MyDelegate1(myP ES.myTest1.myFo o1); //old style
x += myPES.myTest1.m yFoo1;
x(1); //works
x += new MyDelegate1(myP ES.myTest1.myFo o12);
x(10); //works

//////// equivalent

// p. 107 Albahari equivalent: ////////////////
MyDelegate2 x2 = new MyDelegate2(myP ES.myTest1.myFo o2);
x2("Rays");

// MyDelegate2 x2 = null;
//x2 += new MyDelegate2(myP ES.myTest1.myFo o2);
//x2("Ray");
///////////////////////////////////////////////

//MyDelegate3 x3 = null;
//x3 += new MyDelegate3(myP ES.myTest1.myFo o3);
//x3(123, '!');
//x3 += new MyDelegate3(myP ES.myTest1.myFo o32);
//x3(123, '$');

MyDelegate3 myDelegate3Inst ance1 = new
MyDelegate3(myP ES.myTest1.myFo o3);
MyDelegate3 myDelegate3Inst ance2 = new
MyDelegate3(myP ES.myTest1.myFo o32);

MyDelegate3 allInstances_of _Del3 = myDelegate3Inst ance1 +
myDelegate3Inst ance2;

Delegate[] delegateList3 =
allInstances_of _Del3.GetInvoca tionList(); //key, to
use .GetInvocationL ist, which returns an array of Delegate <generic>

Console.WriteLi ne("begin delegate array");

for (int counter = 0; counter < delegateList3.L ength;
counter++)
{
((MyDelegate3)d elegateList3[counter])(1234,'@'); //
note format

}

Console.WriteLi ne("end delegate array");


Console.WriteLi ne("notice chaining of delegates for x3");

MyDelegate4 x4 = null;
x4 += new MyDelegate4(myP ES.myTest1.myFo o4);
x4();
}
//OUTPUT (same as before, works)

hi:1
hi:10
Rays
begin delegate array
i, object are: 1234, @ //<-one of two MyDelegate3 methods
i, object areTWO: 1234, @ //<--two of 2
end delegate array
notice chaining of delegates for x3
myFoo4()...noth ing
The End
Press any key to continue . . .
Oct 10 '08 #5
raylopez99 <ra********@yah oo.comwrote:

Just to address this one bit:

<snip>
Delegate[] delegateList3 =
allInstances_of _Del3.GetInvoca tionList();
//key, to use .GetInvocationL ist, which returns an array of Delegate
<generic! This is key Jon, the use of the .GetInvocationL ist
extension method
a) It's not an extension method
b) You don't need it in this case

If you just call a delegate which contains multiple actions, it will
call each of those actions with the same arguments.

You only need to call GetInvocationLi st and iterate through if you need
to do something with each result, or perhaps invoke all the actions
even if some of them throw an exception.

See P38-40 of C# in Depth for more on this.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Oct 10 '08 #6
>
If you just call a delegate which contains multiple actions, it will
call each of those actions with the same arguments.
Yes, I also noticed this.
>
You only need to call GetInvocationLi st and iterate through if you need
to do something with each result, or perhaps invoke all the actions
even if some of them throw an exception.

See P38-40 of C# in Depth for more on this.
pp. 38-40 of your book did not really bring this out, but yes, the C#
Cookbook recipe indeed use .GetInvocationL ist because in the array it
only invoked every other delegate (for expository purposes).

Thanks again

RL
Oct 10 '08 #7
>The hashtable isn't storing hashtables, it's storing key/value pairs
>where the key is a string and the value is a delegate. It's not exactly
clear what you're trying to do here.

I found a solution that does what I am trying to do--at least the
first of the two questions. If you have the book by O'Reilly "C#
Cookbook" by Hilyard and Teilhet, 2nd ed (Updated for C#2.0), look at
chapter 9, receipe 9.1 "Controllin g when and if a delegate fires
within a multicast delegate". They use an array to store various
delegates, rather than a hash table as in my OP, then they traverse
the array using for() logic. They show how you can traverse backwards
and forwards and skip every other delegate, etc, as you can traversing
any array. Basically one of the two questions was this--how to store
disparate delegates in a container and traverse the container. Of
interest is that you can add delegates of disparate signatures,
exactly as I proposed, e.g., for those who don't have the book before
them reading this thread:
Ahh... you're mixing two different ideas for delegate containment. For
multiple delegates attached to a single event, just use the multicast
delegate, it's all managed for you, and use GetInvocationLi st if you need to
treat the delegates separately for some reason (such as Jon's suggestion of
isolating exception handling to each one individually).

The other one, the use of the Hashtable in the link you provided, has
nothing to do with multiple delegates on a single event. It's solely a
memory-saving measure. The built-in WinForms controls have hundreds of
events. In most cases no more than 3-4 of these actually have handlers
attached. If you used the "normal" way of using a multicast delegate field
for each event, you'd need a pointer-sized (4 or 8 bytes depending on x86 or
x64) chunk of memory in every control instance for every different possible
event. By using the Hashtable, you pay a higher cost per used event (for
the internal hashtable structure) but unused events cost nothing. To make
this work, there's really no way to avoid lots of casting, because you need
all the different kinds of events stuffed into a single Hashtable or
Dictionary (You could use Dictionary<obje ct, EventHandlerins tead of
Hashtable but you'd still need casts.)

I doubt you will ever need to use the Hashtable/Dictionary storage because
most classes you or I design have no more than a dozen or so events, so it's
more space efficient (and typesafe) to just use a field for each.

Oct 10 '08 #8
On Oct 10, 2:39*pm, "Ben Voigt [C++ MVP]" <r...@nospam.no spamwrote:
The hashtable isn't storing hashtables, it's storing key/value pairs
where the key is a string and the value is a delegate. It's not exactly
clear what you're trying to do here.
I found a solution that does what I am trying to do--at least the
first of the two questions. *If you have the book by O'Reilly "C#
Cookbook" by Hilyard and Teilhet, 2nd ed (Updated for C#2.0), look at
chapter 9, receipe 9.1 "Controllin g when and if a delegate fires
within a multicast delegate". *They use an array to store various
delegates, rather than a hash table as in my OP, then they traverse
the array using for() logic. *They show how you can traverse backwards
and forwards and skip every other delegate, etc, as you can traversing
any array. *Basically one of the two questions was this--how to store
disparate delegates in a container and traverse the container. *Of
interest is that you can add delegates of disparate signatures,
exactly as I proposed, e.g., for those who don't have the book before
them reading this thread:

Ahh... you're mixing two different ideas for delegate containment. *For
multiple delegates attached to a single event, just use the multicast
delegate, it's all managed for you, and use GetInvocationLi st if you needto
treat the delegates separately for some reason (such as Jon's suggestion of
isolating exception handling to each one individually).

The other one, the use of the Hashtable in the link you provided, has
nothing to do with multiple delegates on a single event. *It's solely a
memory-saving measure. *The built-in WinForms controls have hundreds of
events. *In most cases no more than 3-4 of these actually have handlers
attached. *If you used the "normal" way of using a multicast delegate field
for each event, you'd need a pointer-sized (4 or 8 bytes depending on x86or
x64) chunk of memory in every control instance for every different possible
event. *By using the Hashtable, you pay a higher cost per used event (for
the internal hashtable structure) but unused events cost nothing. *To make
this work, there's really no way to avoid lots of casting, because you need
all the different kinds of events stuffed into a single Hashtable or
Dictionary (You could use Dictionary<obje ct, EventHandlerins tead of
Hashtable but you'd still need casts.)

I doubt you will ever need to use the Hashtable/Dictionary storage because
most classes you or I design have no more than a dozen or so events, so it's
more space efficient (and typesafe) to just use a field for each.
Excellent! Now it all makes sense. Your words will be hereby
memorialized in my library of wisdom on C# that I am steadily adding
to everyday...than k you.

BTW, I found there's several little traps for the unwary in delgates,
too numerous to mention, but here's one that I like:

// code fragment (don't get too bent out of shape as to what the
method are, just go with it. The point being: you can add Event 10
and Event 20 to form a combined delegate, but only if it's in the
proper format (what I call 'new style' but I think in fact it's pre
C#3 old style), namely using 'new' and WITHOUT the "+=" operator
(which itself is shorthand for a more complicated structure)... see
comments below.

Event10 = new MyDelegate1(myT est1.myFoo1); //'new style'

Event1 += new MyDelegate1(myT est1.myFoo1); //'old style'
Event20 = new MyDelegate1(myT est1.myFoo12);

Event2 += new MyDelegate1(myT est1.myFoo12);
// MyDelegate1 Events1_and_2 = Event1 + Event2;// does not
work! Error: "can only appear on the left hand side of += or -="
//error CS0079

MyDelegate1 Event10_and20 = Event10 + Event20; //but this,
DOES work, though it's exactly the same delegates!

// The end.

RL
Oct 10 '08 #9
raylopez99 <ra********@yah oo.comwrote:

<snip>
// code fragment (don't get too bent out of shape as to what the
method are, just go with it. The point being: you can add Event 10
and Event 20 to form a combined delegate, but only if it's in the
proper format (what I call 'new style' but I think in fact it's pre
C#3 old style), namely using 'new' and WITHOUT the "+=" operator
(which itself is shorthand for a more complicated structure)... see
comments below.

Event10 = new MyDelegate1(myT est1.myFoo1); //'new style'
Event1 += new MyDelegate1(myT est1.myFoo1); //'old style'
Both of those would have been valid in C# 1, assuming Event10 really is
referencing a variable rather than an event. Neither is a "new style".
The difference is that one is using assignment, and the other is
combining the two delegates - the result seems pretty obvious to me!

What *is* "new" in C# 2 is the ability to write:

Event10 = myTest1.myFoo1;
Event1 += myText1.myFoo1;
Event20 = new MyDelegate1(myT est1.myFoo12);

Event2 += new MyDelegate1(myT est1.myFoo12);
// MyDelegate1 Events1_and_2 = Event1 + Event2;// does not
work! Error: "can only appear on the left hand side of += or -="
//error CS0079
Yes, you can only subscribe/unsubscribe from an event, not assign to it
or fetch a "current" value.
>
MyDelegate1 Event10_and20 = Event10 + Event20; //but this,
DOES work, though it's exactly the same delegates!
My guess is that Event1 and Event2 are proper events, whereas Event10
and Event20 are variables (or field-like events in the same class).

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Oct 11 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
3925
by: IceShock | last post by:
I have been studying the C# language for sometime now and i have noticed something about delegates. When are single cast delegates to be used? even a better question: How do we define a singlecast delegate? The thing is I have been using the .net v 1.1 2003 frame work and i have been told that this might be the issue. I have been told...
1
2832
by: Natalia DeBow | last post by:
Hi, I am working on a Windows-based client-server application. I am involved in the development of the remote client modules. I am using asynchronous delegates to obtain information from remote server and display this info on the UI. From doing some research, I know that the way my implementation works today is not thread-safe, because...
4
22859
by: LP | last post by:
Hello! I am still transitioning from VB.NET to C#. I undertand the basic concepts of Delegates, more so of Events and somewhat understand AsyncCallback methods. But I need some clarification on when to use one over another? If anyone could provide any additional info, your comments, best practices, any good articles, specific examples, etc....
1
3387
by: Christoph Nahr | last post by:
The task: I want to let a background thread and a Windows Forms foreground thread communicate via callback methods. Now synchronization of a *single* delegate works just fine with the usual Control.Invoke or Control.BeginInvoke methods. However, I couldn't find any information on using this technique with multicast delegates, i.e. the...
1
1190
by: Hiten | last post by:
Hi I have created multicast delegates, now i want to point to perticular reference from delegate to invoke that mathod how do i do that please any one know it..... Thanks --- Hitendra
5
3868
by: GVN | last post by:
Hi All, I recently worked on delegates. But I have a question regarding Multicast delegates. The scenario is as follows: I have a delegate myDelegate with object dlgt, and two methods myMethod1(), and myMethod2(). Using multicast delegates definition I can write as follows to add the two methods to my multicast delegate:
7
8435
by: pietro.cerutti | last post by:
Hi guys, I have a daemon running on Debian and listening for multicast packets sent to 224.0.0.251:5353 (ZeroConf Multicast DNS queries). The server is plugged into a VLAN trunk with eth0 and joins several VLANs using virtual interfaces (i.e. eth0.xxx). It should be able to capture the UDP packets on any interfaces, so it spawns a thread for...
2
1752
by: =?Utf-8?B?aGVyYmVydA==?= | last post by:
What are the different features (in VB.NET) between a) Custom Events and b) Multicast Delegates to raise events? On the bottom line my class ad a) manages a list of handlers or ad b) obtains a list of handlers (using GetInvocationList) and invokes them one-by-one. So where is the difference? eg are Custom Events the only way to raise an...
5
8898
by: AliRezaGoogle | last post by:
Hi, I have a conceptual question on Events and Multicast Delegates. Let me explain: As we know an event is a multicast delegate. What we declare as an event is inherently a multicast delegate. I really do not undrestand what additional features the "event" keyword adds to multicast delegate. The only thing that I see as an additional...
0
7439
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7376
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7633
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7785
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7395
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
3433
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3425
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1851
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
997
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.