force get/set access of private variables for priv

2020-07-13 08:03发布

If I have a private variable that I want to have some internal validation on, and I want to keep that validation in one place, I put it behind a getter/setter and only access it thorugh that getter/setter. That's useful when dealing with public properties, because the other code cannot access the private variable, but when I'm dealing with object inside the class itself, is there any way to enforce the getter/setter?

  private int _eyeOrientation;

  private int eyeOrientation
  {
     get
     {
        return _eyeOrientation;
     }
     set
     {
        if (value < 0)
        {
           _eyeOrientation = 0;
        }
        else
        {
           _eyeOrientation = value % 360;
        }
     }
  }

The issue here being that the other functions in the class may accidentally modify

_eyeOrientation = -1;

which would throw the program into a tizzy. Is there any way to get that to throw a compiler error?

标签: c#
6条回答
SAY GOODBYE
2楼-- · 2020-07-13 08:21

Sounds like you need a angle type.

// Non mutable Angle class with a normalized, integer angle-value
public struct Angle
{
  public Angle(int value)
  {
    Value = value;
  } 

  private angle;
  public Value 
  { 
    get { return angle; } 
    private set { angle = Normalize(value); } 
  }

  public static int Normalize(int value)
  {
     if (value < 0) return 360 - (value % 360);
     return value % 360;
  }
}

public class SomeClass
{
  public Angle EyeOrientation { get; set; }
}

If you have a certain kind of value, like angles, money, weight or whatever, it is always a good praxis to make it a own type, even if the value itself is stored in a int, decimal etc. This type makes your interfaces clearer and typesafe. It is not the same if you expect an Angle or a integer value as argument of some method.

查看更多
地球回转人心会变
3楼-- · 2020-07-13 08:27

Depending on your tools you could look into enforcing a coding convention not allowing direct access to a private member outside a get/set

Might be some more work but you won't have to create a series of wrapper classes.

查看更多
够拽才男人
4楼-- · 2020-07-13 08:32

Just put your private attribute and public getters/setters into a private class.

Then only the getter and setter can access the private attribute.

It is overkill but would work. :)

查看更多
我欲成王,谁敢阻挡
5楼-- · 2020-07-13 08:37

In general, you shouldn't worry about this. Class members can still use the properties, if you don't want to put the checking in the class itself.

If your class is getting so large that you no longer trust methods inside the class, I'd think that it's time to start refactoring and breaking this into smaller classes that are more easily managable.

查看更多
啃猪蹄的小仙女
6楼-- · 2020-07-13 08:37

You can mark the field as obsolete so that the compiler will generate a warning if you try to access it, and then suppress that warning for the property getter/setter.

The warning codes that you'd need to suppress are CS0612 for the plain Obsolete attribute and CS0618 if the attribute has a custom message.

In general I'd consider this a bit of a hack and try to avoid it if possible. A better solution would be to comment the code appropriately and train your fellow developers so that they'll do the right thing.

[Obsolete("Please use the EyeOrientation property instead.")]
private int _eyeOrientation;

public int EyeOrientation
{
    #pragma warning disable 612, 618
    get
    {
        return _eyeOrientation;
    }
    set
    {
        _eyeOrientation = (value > 0) ? value % 360 : 0;
    }
    #pragma warning restore 612, 618
}
查看更多
别忘想泡老子
7楼-- · 2020-07-13 08:47

You could possibly define it in a nested class.

public class NeedsEye
{

    Eye _eye = new Eye();

    public NeedsEye()
    {
        // now, here, any access to the property must be made through the
        // _eye variable. The Eye class has access to any of the properties
        // and members of the NeedsEye class, but the NeedsEye class has not
        // any access to members of the Eye class.
    }

    private class Eye
    {
        private int _orientation;

        public int Orientation 
        {
            get { return _orientation; }

            if (value < 0)
            {
               _eyeOrientation = 0;
            }
            else
            {
               _eyeOrientation = value % 360;
            }     
        }
    }
}
查看更多
登录 后发表回答