C#Structs,事件和构造函数

时间:2017-06-30 09:35:17

标签: c# events struct constructor initialization

如果想要拥有一组值,并在该集合发生更改时通知,则可以使用ObservableCollection及其CollectionChanged事件。

但是,只有在修改集合本身时才触发它的CollectionChanged事件,而不是它包含的值。例如,如果我有ObservableCollection<Image>,我将无法检测到有人访问集合的第N个图像并调用修改它的方法。如果我有一个ObservableCollection<Color>,那同样的事情也是如此。如果我希望能够监视列表中包含的Color结构何时被分配,则项目本身必须是可观察的(递归地)。 Color结构不可观察,我想将其封装到名为ObservableColor的结构中。

问题在于,编译器对我大吼大叫,因为事件没有在构造函数中初始化。首先,我不知道一个事件必须被初始化,其次我不知道它应该如何被初始化。

以下是我的代码:

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"));
        }
    }
}

如何进行编译?谢谢。

2 个答案:

答案 0 :(得分:2)

C#要求在值类型的构造函数中显式初始化所有字段。您收到此错误只是因为PropertyChanged在构造函数完成之前未分配任何内容。解决这个问题很简单,只需这样做:

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

那就是说,你应该考虑改变你的方法。可变结构是所有类型的头痛,意外行为和微妙的错误的来源,可以让你发疯。我建议将ObservableColor更改为引用类型。

答案 1 :(得分:0)

正如评论中已经提到的,mutable structs are evil。因此,进行此编译的最佳方法是将此类型设为class

class ObservableColor : INotifyPropertyChanged
{...}

如果您确实需要这是struct,那么您的构造函数必须初始化struct的所有字段,甚至是event

struct ObservableColor : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Color Value { get; private set; }

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