Théo Farnole
Théo Farnole

Reputation: 103

Force usage of the private property even if there is the private field?

I am using a set private property to do an extra job. The problem is that, sometimes, I am setting the variable instead of the property.

I'd like to know if there is a way to avoid this.

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 :/
}

Thanks for reading! Theo

PS: I am using Unity 2019 and I set API compatibility level to .NET 4.x Equivalent

Upvotes: 1

Views: 384

Answers (3)

Scott Hannen
Scott Hannen

Reputation: 29207

You can't declare a variable and somehow prevent using it. If you want an int that invokes another method when it's modified, you could declare it as another class. Here's an example. The names are atrocious, as I don't know how to name this to describe what you're trying to accomplish.

Note that this is not a replacement for your class. This is a replacement for your int. It encapsulates an int (or any other type) with a method that is invoked when the value is updated.

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

    public T Value => _value;

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

    protected abstract void ExtraWork();
}

Or

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

This doesn't prevent setting _value, because you can't. But now in the class where you were using an int field you would use ValueThatInvokesMethodWhenItsUpdated<int>.

So all this does is add another level of encapsulation.

But this is likely an over-complication. Since you're the one defining your class, the far simpler approach is simply to not set the field that you don't want set.

Upvotes: 1

John Wu
John Wu

Reputation: 52230

The only way I know how to do this is to define a separate (possibly abstract) class and inherit from it. When you do that, you can make the property protected and the field private, like so:

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
    }
}

See a working example on DotNetFiddle

Upvotes: 1

user3818619
user3818619

Reputation:

You could use [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] to hide it from IntellisSense. You will still be able to use it regardless, if you type it out, but you won't get autocomplete for it.

Ultimately there only way to really forbid yourself from using it, would probably to define your own Attribute and configure something like Resharper to mark the usage of fields with this attribute as an error, but I'm not sure if Resharper can be configured like this.

Upvotes: 3

Related Questions