-2

Consider the following built-in delegate:

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

Is it possible that I extend/overload/override the delegate to this signature:

public delegate void MyPropertyChangedEventHandler(object sender,
        MyPropertyChangedEventArgs e);

where MyPropertyChangedEventArgs is declared as

public class MyPropertyChangedEventArgs : PropertyChangedEventArgs
{
    public readonly object OldValue;
    public readonly object NewValue;

    public MyPropertyChangedEventArgs(string propertyName, object 
        oldValue, object newValue) : base(propertyName)
    {
        OldValue = oldValue;
        NewValue = newValue;
    }
}

and the class that owns the event is declared as

using System;
using System.ComponentModel;

// missing delegate decleration

public class Bindable : INotifyPropertyChanged
{
    public event MyPropertyChangedEventHandler PropertyChanged;

    private object _property;
    public object Property 
    {
        get { return property; }
        set 
        {
            var oldValue = _property;
            _property = value;
            OnPropertyChanged("Property", oldValue, value);
        }
    }

    protected void OnPropertyChanged(string name, object oldValue,
            object newValue)
    {
        if (oldValue != newValue && PropertyChanged != null)
            PropertyChanged(this, new MyPropertyChangedEventArgs(name,
                    oldValue, newValue));
    }
}

and event subscription should allow access to MyPropertyChangedEventArgs properties without needing to type cast the PropertyChangedEventArgs everywhere and still not lose the out-of-the-box XAML binding to the property.

Example use-case:

Bindable bindable = new Bindable();

bindable.PropertyChanged += (sender, args) =>
{
    if (args.OldValue != null)
    {
        // Do Something
    }
};
anragab
  • 11
  • 4

1 Answers1

0

Assuming MyPropertyChangedEventArgs derives from PropertyChangedEventArgs (you aren't clear about this in your question), then delegate contravariance will certainly allow client code to subscribe to your "extended" PropertyChanged event using handlers that match only the basic PropertyChangedEventHandler. This is safe, because those handlers promise that they can accept a PropertyChangedEventArgs instance, and the object your code will pass is in fact one of those (though more derived).

That said, if there is binding-related code that is checking for a specific return value, it could fail simply because it didn't find the event it was looking for. If you are sure that this is not a problem in your scenario (which is poorly defined here…a complete, minimal code example would really help the question quality here), then I guess you don't need to worry about it per se.

But it would still be somewhat "iffy" design to do this. IMHO, it would be better to define a second event (named e.g. MyPropertyChanged or, more idiomatic in the .NET/C# world, PropertyChangedEx with a similar name for the EventArgs subclass). Then when the property changes, raise both events. On any modern computer (including mobile platforms), this minimal extra overhead will be completely insignificant, and the benefit is a much cleaner, easier to use API.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • I have just edited the Question to clarify my intentions that were not clear to you. Was that constructive? – anragab Jan 16 '15 at 10:30
  • Based on your edits (which seem to mainly just confirm my assumptions), it's my opinion that my suggestion that you implement two different events is the best one. If that doesn't work for you, it would be more productive for you to explain in detail why that particular solution doesn't seem appropriate or useful to you. – Peter Duniho Jan 16 '15 at 17:05