使变量只能通过其set属性设置

时间:2019-07-02 12:15:24

标签: c#

我有一个布尔变量,我希望对其值的每次更改都能调用一段代码。

我当前的解决方法如下:

bool _manualControl;
bool manualControl {
    get {
        return _manualControl;
    }
    set {
        this._manualControl = value;
        GlobalEventManager.ManualControlEvent?.Invoke(value);
    }
}

此解决方案有两个问题:

  1. “ _ manualControl”的值可以在内部更改而无需调用我的代码,我想防止这种情况。
  2. 我宁愿避免使用两个变量来获得所需的行为。

在避免这两个特定问题的同时,有什么方法可以实现我想要的?

3 个答案:

答案 0 :(得分:4)

您可以将属性设置为public,并有一个private支持字段,只能在您可以控制的类中进行修改。

或者您可以使用诸如PostSharp之类的面向方面的编程框架,该框架将允许您使用auto属性并以所需的行为对其进行注释。这样就不需要您具有后备字段了。

答案 1 :(得分:4)

对我来说,这听起来像是您想解决体系结构问题(又称代码气味)。为什么您担心自己的领域可能不在二传手之外呢?是很多人在不真正知道自己在做什么的情况下进行的特别大的课程吗?

为什么设置器中甚至有代码?就像您可以重新设计代码,让一种方法执行设置程序代码所做的那样,并将其引入代码流/流程中。

并进行单元测试以验证您所需的行为。

答案 2 :(得分:1)

如果您想:

  • 确保在分配新值时(类的内部和外部),setter代码始终执行
  • 避免在类中有两个表示单个值的成员

然后可以通过将值包装在类似以下结构的结构中来实现:

struct Intercepted<T>
{
    private readonly Action<T> _onChange;
    private T _value;

    public Intercepted(Action<T> onChange, T initialValue = default(T))
    {
        _onChange = onChange;
        _value = initialValue;
    }

    public T Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            _onChange?.Invoke(value);
        }
    }
}

在类中,ManualControl现在可以由类型为Intercepted<bool>的单个成员表示:

public Intercepted<bool> ManualControl { get; } = new ManualControl(
    onChange: newValue => {
        GlobalEventManager.ManualControlEvent?.Invoke(newValue);
    }
);

可以像这样访问值:

// from within the class
if (ManualControl.Value) { ... }

// from outside
myObj.ManualControl.Value = true;

现在,在类的内部和外部,都无法在不触发设置器代码的情况下更改值。