Search code examples
c#unity-game-engineencapsulation

Unity Encapsulation, property force me to rewrite variables names?


I want to understand a simple thing.

I am reading a lot of questions, answers about Encapsulate in Unity and C#. It is all talking about get/set and most of the answers saying that the top benefit of get and set is to stop mistyping or something I write in any other script to access my variable and make problem for my program.

So, if I am really focused and I don't make a mistake like get/set becoming null! I mean, there is no other real benefits.

Also, I see that property force me to rewrite the variables name, so much

Like this:

private int health 
public int health { get; private set; }

So the result is that I make more complex code. I make more same names in my script, that is not dangerous?


Solution

  • You're example isn't working because health is the same variable twice. The common convention is to use _health or health for the backing field and Health for the property (get/set/). Also, there's nothing stopping you from doing:

    private int backingField;
    public int OtherProperty { get { return backingField; } } 
    public int Property => backingField; // Does same thing as above
    

    It would just be very confusing for you, your future self, and your coworkers.

    However, in your case, you can just do this:

    public int Health { get; private set; }
    

    So, if I am really focused and I don't make a mistake

    This is a really bad mindset. You're gonna shoot yourself in the foot if you keep doing this mindset, because you can't focus on everything at the same time. The brain can only have so much information loaded at once. The idea is to not allow yourself to make mistakes.

    My programmer professor once said that that mindset is like leaving your baby on one lane of the highway, and if a car comes you just move it to the other lane. You could do that forever, or you could just not have your baby anywhere near the highway.

    Visual Studio makes it really easy to rename things and you only need to do that once. The better power of get/set is to make sure the data is valid. For example

    private int _age = 0;
    public int Age
    {
        get => _age;
        set
        {
            if (value > 0)
                _age = value;
        }
    }
    

    This code will prevent the user from setting Age to be a negative number, because that's impossible.

    Properties are amazing and there's lots of cool things you can do with them, like this:

    public struct Rectangle
    {
        public int X, Y;
        public int Area => X * Y;
        
        public Rectangle(int x, int y) => (X, Y) = (x, y);
    }
    

    public int Area => X * Y; is a property, though it doesn't look it. It's the same as:

    public int Area
    {
        get
        {
            return X * Y;
        }
    }
    

    What's cool is that Area only has a getter therefore the value of it can't be changed. Area = 3 won't work. This is ideal, because that would make invalid data.

    Effectively, all Area is is syntactic sugar for a method GetArea() => X * Y;, but we instead don't use Get prefix or the () at the end.

    When are properties useful

    In summary, properties (get/set) are useful to make the setting of the variable private or protected to prevent invalid data from leaking in, having something fire when the setter is used to make sure the new data is valid, or having something that looks like a readonly variable but it actually executes a quick calculation to get the data.

    They are great for encapsulation in that sense.

    Edit: As Draco18s pointed out, they are also useful for interfaces, which are like classes, but one of the differences being they can't have fields. They can however, have properties, as, under the hood, properties are just methods.