Why is this delegate assignment not working and how to solve it?

I have the following example code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.del = this.EventHandler; <-- This does not build
    }

    public void EventHandler(object sender, PropertyChangedEventArgs e)
    {

    }

    public delegate void A(object sender, EventArgs e);

    private A del;
}

      

He complains about the appointment of a delegate. I suspect it has something to do with covariance / contravariance issues, which, frankly, is a concept I don't fully understand.

Is there a way to do this assembly of code? I need a generic handler for any event with any args events (inheriting from EventArgs).

+3


source to share


5 answers


Imagine this line is compiled:

        this.del = this.EventHandler;

      

Then here comes the problem:

        // since del must accept ANY EventArgs descendant, this should be possible:
        del.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
        // since del signature IS (object, PropertyChangedEventArgs), we must convert 
        // NotifyCollectionChangedEventArgs to PropertyChangedEventArgs
        // OOOPS...

      



I need a generic handler for any event with any args events

Use a handler with this signature:

public void EventHandler(object sender, EventArgs e)
{

}


// compiles just fine
this.Loaded += EventHandler;
this.Closing += EventHandler;
this.Drop += EventHandler;

      

+2


source


You can find an explanation of delegate variance and covariance here



When you assign a method to a delegate, covariance and contravariance provide the flexibility to map the delegate type using the method signature. Covariance allows for a return method of a type that is larger than that defined in the delegate. Contravariance resolution is a method that has parameter types that are less derived than those cast in the delegate type.

+1


source


The method signature must match delegate

. If what you are trying to do is allowed, you can pass any type to the second parameter that inherits from EventArgs

, but it really expects PropertyChangedEventArgs

.

0


source


It cannot work like this. In your code example, your method EventHandler

requires to e

be of a type PropertyChangedEventArgs

, that is, a more specific type than what the delegate has declared.

It will work the other way around, i.e. your handler may be less specific than the delegate.

0


source


It should be

Use PropertyChangedEventArgs

in Method A Overload

Because when assigning an event to any delegate. their signature must be the same

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.del = this.EventHandler; <-- This does not build
    }

    public void EventHandler(object sender, PropertyChangedEventArgs e)
    {

    }

    public delegate void A(object sender, PropertyChangedEventArgs e);

    private A del;
}

      

0


source







All Articles