即使存在私有字段,也强制使用私有财产吗?

时间:2019-07-17 01:34:53

标签: c# unity3d properties

我正在使用已设置的私有财产来做额外的工作。 问题在于,有时我会设置属性变量 代替

我想知道是否有办法避免这种情况。

private int _directionX = -1;

private int DirectionX
{
  get
  {
    return _directionX;
  }

  set
  {
    _directionX = value;

    ExtraWork();
  }
}

private void Start()
{
  // the problem is that I can do :
  _directionX = 0;
  // and so, property is bypassed :/
}

感谢您的阅读! 西奥

PS:我正在使用 Unity 2019 ,并将API兼容级别设置为 .NET 4.x等效版本

3 个答案:

答案 0 :(得分:3)

您可以使用[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] 将其从IntellisSense中隐藏。无论您键入什么内容,仍然可以使用它,但是不会自动完成。

最终只有一种真正禁止自己使用的方法,可能是定义自己的属性并配置诸如Resharper之类的东西,以将该属性标记为错误的字段的使用,但是我不确定Resharper是否可以这样配置。

答案 1 :(得分:1)

我知道如何执行此操作的唯一方法是定义一个单独的(可能是抽象的)类并从中继承。这样做时,您可以将属性设置为保护状态并将字段设置为私有,如下所示:

abstract class PrivateFoo
{
    private int _directionX = -1;

    protected int DirectionX
    {
      get
      {
        return _directionX;
      }

      set
      {
        _directionX = value;

        ExtraWork();
      }
    }

    protected abstract void ExtraWork();

    protected abstract void Start();
}

class Foo : PrivateFoo
{

    protected override void ExtraWork()
    {
    }

    protected override void Start()
    {
        this.DirectionX = 0;     //Compiles
        _directionX = 0;         //Does not compile
    }
}

查看working example on DotNetFiddle

答案 2 :(得分:1)

您无法声明变量,并以某种方式阻止使用它。如果希望int在修改后调用另一个方法,则可以将其声明为另一个类。这是一个例子。这些名字很残酷,因为我不知道如何命名来描述您要完成的工作。

请注意,这不能代替您的课程。这是您的int的替代品。它使用值更新时调用的方法封装int(或任何其他类型)。

public abstract class ValueThatInvokesMethodWhenItsUpdated<T>
{
    private T _value;

    public T Value => _value;

    public void SetValue(T value)
    {
        _value = value;
        ExtraWork();
    }

    protected abstract void ExtraWork();
}

public class ValueThatInvokesMethodWhenItsUpdated<T>
{
    private T _value;
    private readonly Action _extraWork;

    public ValueThatInvokesMethodWhenItsUpdated
        (Action extraWork)
    {
        _extraWork = extraWork;
    }
    public T Value => _value;

    public void SetValue(T value)
    {
        _value = value;
        _extraWork?.Invoke();
    }
}

这不会阻止设置_value,因为您不能这样做。但是现在在您使用int字段的类中,您将使用ValueThatInvokesMethodWhenItsUpdated<int>

因此,所有要做的就是添加另一个封装级别。

但这可能是一个过度复杂的问题。由于您是定义类的人,因此简单得多的方法是设置不需要的字段。