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.

Robert Harvey
201k55 gold badges469 silver badges682 bronze badges
asked Mar 2, 2020 at 15:01
13
  • 1
    fody propertychanged Commented 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. Commented Mar 2, 2020 at 15:24
  • 1
    Really. I would close this as duplicate, if we could mark SO questions as duplicates. Commented 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. Commented 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. Commented 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.

answered Mar 2, 2020 at 15:19
7
  • This does require C# 6.0. Commented 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)' Commented 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 -=..." Commented 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. Commented Mar 2, 2020 at 17:07
  • 1
    This does not compile Commented Mar 3, 2020 at 12:50

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.