1

When one wants to have a collection of values, and be notify when that collection changes, the ObservableCollection and its CollectionChanged event can be used.

However, its CollectionChanged event is only fired when modifying the collection itself, not the values it contains. For example, if I have an ObservableCollection<Image>, I won't be able to detect when someone accesses the N-th image of the collection and calls a method that modifies it. he same thing is true if I have an ObservableCollection<Color>. If I want to be able to monitor when a Color struct contained within the list is assigned, the items themselves must be observable (recursively). A Color struct not being observable, I want to encapsulate it into a struct called ObservableColor.

The problem is that, the compiler is yelling at me because the event is not being initialized in the constructor. Well first I didn't know an event had to be initialized, and second I have no idea how it is supposed to be initialized.

Below is my code :

struct ObservableColor : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Color Value { get; private set; }

    public ObservableColor(Color color)
    {
        Value = color;
    }

    public void Set(Color color)
    {
        Color oldColor = Value;
        Value = color;
        if (Value != oldColor)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value"));
        }
    }
}

How can I make this compile ? Thank you.

Virus721
  • 8,061
  • 12
  • 67
  • 123
  • 1
    What exactly does the compiler yell? – Sean Reid Jun 30 '17 at 09:37
  • Actually it's not exactly the compiler, it's whatever checks the code on the fly. It says "Field ObservableColor.PropertyChanged" must be fully assigned before control is returned to the caller" whenever I hover the red underlined constructor name. – Virus721 Jun 30 '17 at 09:43
  • 3
    I would highly recommend making this a class rather than a struct in any case - mutable structs are evil – Sean Reid Jun 30 '17 at 09:43

2 Answers2

5

C# requires that all fields be explicitly initialized in a value type's constructor. You are getting this error simply because PropertyChanged is not assigned anything before the constructor finishes. Fixing this is trivial, just do this:

public ObservableColor(Color color)
{
    Value = color;
    PropertyChanged = null;
}

That said, you should consider changing your approach. Mutable structs are source of all kind of headaches, unexpected behavior and subtle bugs that can drive you crazy. I'd recommend changing ObservableColor to a reference type.

InBetween
  • 32,319
  • 3
  • 50
  • 90
1

As already mentioned in the comments, mutable structs are evil. So the best way to make this compile is to make this type a class:

class ObservableColor : INotifyPropertyChanged
{...}

If you really need this to be a struct, then your constructor has to initiaize all fields of the struct, even the event:

struct ObservableColor : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Color Value { get; private set; }

    public ObservableColor(Color color)
    {
        Value = color;
        PropertyChanged = null; // initiailze
    }
René Vogt
  • 43,056
  • 14
  • 77
  • 99