0

In a C# application, I've got a behaviour that I would like to be available in different classes that not necessarily share the same ancestor. What better opportunity to 'favour composition over inheritance?"

In this case not only composition is a better way, but can also be the only way.
Unfortunately, the code is the following. I left only the relevant part, obviously it would make little sense to delegate only this, but this is the problematic part.

public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

   }

Turns out that since PropertyChanged is an event, it can only be raised inside the declaring class.

I evaluated all the proposed alternatives to this, found in this S&O question: Alternatives and all of them seems a bit of a hack. That is, events are not meant to be delegated. Fundamentally, I would like that someone proof me to be wrong on this point.

Unfortunately this seems to be another case of the pattern: you use inheritance? no no no, there is a better approach. And when you try to implement it you suddenly bump into problems that require various levels of hacking the language or bringing complexity of the solution to an whole other level.

At the end of the day inheritance or composition is not a marriage, so I don't want to stay with either of them for life; I considered myself to be married with the non-duplication, or DRY principle. So I wanted to find a good way of not repeating the code. Here I simply cannot find a reasonably-simple solution and hope that someone else that has already bumped into this problem proposed some perhaps 'third way' solution.

13
  • 1
    fody propertychanged
    – Ewan
    Mar 2, 2020 at 15:19
  • INPC has been major PITA since it was created. There are multiple ways people tried to simplify it or code-gen it or whatever. Quick research should show you all the available options.
    – Euphoric
    Mar 2, 2020 at 15:24
  • 1
    Really. I would close this as duplicate, if we could mark SO questions as duplicates.
    – Euphoric
    Mar 2, 2020 at 15:31
  • 2
    Insisting on composition over inheritance (and absolute DRY) is just more dogma for no good reason. Use the right tool for the right job. Mar 2, 2020 at 15:35
  • 1
    FWIW, I just use Fody.PropertyChanged on all my classes that require an INotifyPropertyChanged implementation. Problem solved, no inheritance required. Mar 2, 2020 at 15:40

1 Answer 1

4

There are certain things that do require inheritance. In absence of other language features, this example would be one of them. Note that the phrase is to favor composition over inheritance. That does not mean throw out inheritance where it is warranted.

However, C# specifically does provide a nice out here. That's the use of Extension Methods. Since INotifyPropertyChanged declares the event and the identifies the behavioral pattern, you can implement the specific feature you are talking about using this feature:

public static class FrameworkExtensions
{
    public static void NotifyPropertyChanged(this INotifyPropertyChanged model,
            [CallerMemberName] string property = "")
    {
        model.PropertyChanged?.Invoke(model, new PropertyChangedEventArgs(property));
    }
}

The important thing to make it a reality is that the user needs to import the namespace this is declared in. If there are other framework classes that are commonly used in code, that is probably done for you.

7
  • This does require C# 6.0.
    – helb
    Mar 2, 2020 at 15:34
  • 2
    It still does not compile. error CS4022: The CallerMemberNameAttribute may only be applied to parameters with default values. Fix that and you get error CS0079: The event 'INotifyPropertyChanged.PropertyChanged' can only appear on the left hand side of += or -= and error CS7036: There is no argument given that corresponds to the required formal parameter 'e' of 'PropertyChangedEventHandler.Invoke(object, PropertyChangedEventArgs)'
    – Sean Reid
    Mar 2, 2020 at 15:37
  • Doesn't work with either .NET 4.6 and .NET 4.7. Same error "The event 'INotifyPropertyChanged.PropertyChanged' can only appear on the left hand side of += or -=..."
    – AgostinoX
    Mar 2, 2020 at 16:03
  • 3
    @helb, C# 6 was released five years ago. If someone is still using an even older version of the compiler, then needing to use inheritance for this task is the least of their problems.
    – David Arno
    Mar 2, 2020 at 17:07
  • 1
    This does not compile
    – Blake
    Mar 3, 2020 at 12:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.