4

Is it possible to create a list containing delegates of different types ? For example considere this two delegates :

class MyEventArg1 : EventArgs {}
class MyEventArg2 : EventArgs {}

EventHandler<MyEventArgs1> handler1;
EventHandler<MyEventArgs2> handler2;

I would like to do something like that :

List<EventHandler<EventArgs>> handlers = new List<EventHandler<EventArgs>>();

handlers.Add((EventHandler<EventArgs>)handler1);
handlers.Add((EventHandler<EventArgs>)handler2);

But the cast from one delegate to another seems not possible. My goal is to store the delegates in a list not to call them; but just to unregister them automaticly.

Thanks

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
noon
  • 335
  • 1
  • 3
  • 11

3 Answers3

1

You will be able to do this in C# 4.0 thanks to the generics variance but until then you need to find another way (maybe ArrayList).

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

Yes, this doesn't work, the delegates are completely unrelated types. Normally, generic types would have only System.Object as the common base type. But here, since they are delegates, you could store them in a List<Delegate>. I doubt that's going to help you getting them unregistered though. But I can't really envision what that code might look like.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

It's possible for a generic delegate declaration to specify that certain type parameters should be covariant or contravariant, which would allow the types of assignments you're after. Unfortunately, the internal implementation of multicast delegates makes it impossible to combine delegates of different types (a "simple" delegate holds information about its type, along with a method pointer and a reference to its target; a multicast delegate information about its type along with holds the method pointers and target references for each of its constituent delegates, but does not hold any reference to the original delegates that were combined, nor does it hold any information about their types). An attempt to combine an EventHandler<DerivedEventArgs> with an EventHandler<EventArgs> will thus fail at run-time.

If EventHandler<T> were contravariant with respect to T, an attempt to pass an EventHandler<EventArgs> to a standard event AddHandler method which expects an EventHandler<DerivedEventArgs> would compile, and would even succeed if no other handlers were subscribed, since the EventHandler<EventArgs> would be Delegate.Combined with null, thus being stored in the event's delegate field as an EventHandler<EventArgs>. Unfortunately, a subsequent attempt to add anEventHandler<DerivedEventArgs> (which is actually the expected type) would fail since its type doesn't match the delegate it's being combined with. Microsoft decided this behavior would violate the Principle of Least Astonishment (if passing the "wrong" delegate will cause any problem, it should do so when that delegate is passed, rather than when a later one is passed), and decided to minimize the likelihood of the scenario by making it so that an attempt to pass an EventHandler<EventArgs> to a handler that expects an EventHandler<DerivedEventArgs> will fail compilation, even though the act could succeed if it was the only subscription.

supercat
  • 77,689
  • 9
  • 166
  • 211