Problem with {get; set;}

I have these two scripts:

public class PlayerStats {

    private int health = 100;
    private float strength = 500f;

    public float Strength { get; set; }

    public int Health {
        get { return health; }
        set { health = value; }
    }
}
public class PlayerScript : MonoBehaviour {

    PlayerStats stats = new PlayerStats();

    void Start() {
        Debug.Log("Player Health: " + stats.Health);

        Debug.Log("Player Strength: " + stats.Strength);
    }
}

When I write get {return health; } and set {health = value; } prints the ‘health’ value to the console, but when I use the shorthand around property {get; set; } to print the value of the ‘strength’ field, it is printing the value 0, not the value 500 that I defined.

Why can’t I print the value 500? What is wrong with this shorthand?

You didn’t implement it the same as your Health property: you are not returning the strength field explicitly.

Instead, you have an “auto-implemented property” which connects itself to a field created automatically by the compiler. This field won’t be called strength, but something like __strength.

Write out your Strength property in the same syntax as your Health property.

I changed the ‘strength’ field to _strength, but it didn’t resolve.
Could you change the script and post it again with corrections? This will facilitate my understanding.

You can’t guess what field name the auto-implemented properties will use. The compiler will always avoid a conflict with the fields you use explicitly.

public class PlayerStats {

    private int health = 100;
    private float strength = 500f;

   public float Strength {
        get { return strength; }
        set { strength = value; }

    public int Health {
        get { return health; }
        set { health = value; }
    }
}

This syntax I already know how to use and write. Now I want to learn using {get; set}.

My intention is to study the use of auto-implemented property, to know when to use them. That’s why I used {get; set;}

If I want to work with {get; set;} only, where can I use {get; set;} and how to write correctly?

Property is not a shortcut to a variable of the same name. (it can be when you want it to, as you have with Health)
When you do float Strength {get;set;} compiler will create underlying variable (with some “unknown name”).

The property will work as you wrote it, but it won’t get the values entered from the Unity editor. This is a limitation of the editor.

I believe there are extensions you can install to support this scenario, but that’s just beyond my area of expertise.

This seems relevant: Exposing Properties in the Inspector

If you’re trying to make a game, there’s no reason to use the {get; set;} thing. It solves an obscure problem that Unity can’t have.

A regular variable: “public float strength;” is just fine. If you want to turn it into a property later (like Health, except have it do something), you can without a problem.

2 Likes

For me property is just another place where to write code, if i don’t need i don’t use it.
protected,
private (eventually [SerializeField]),
public (eventually [HideInTheInspector]) seems to do the trick most of the time.

I think this is what the topic starter was looking for:

public class PlayerStats {

    public float Strength { get; set; }

    public PlayerStats() {
        Strength = 500f;
    }
}

Default values (=500f) are only supported in a higher C# version. For now you’ll have to use the constructor to assign a value.

When fully public like this the main advantage over a field is that you can turn it into an abstract definition, which you can’t do with a field.

You can also make the setter private or protected, which enables you to restrict the writing access while keeping the reading access public. This split in access is also not possible with a field.

Check this out code written by @TheZombieKiller .

https://discussions.unity.com/t/719343/6

With the code in that link this:

using UnityEngine;

public class Enemy : MonoBehaviour
{
    [field: SerializeField]
    [field: RenameField(nameof(Health))]
    public float Health { get; set; } = 1.0f;
}

Results in this:
5247617--524099--upload_2019-12-4_19-41-51.png

Unity added support for C# 7.3 (the required version to use default values) with 2018.3.

https://blogs.unity3d.com/2018/12/13/introducing-unity-2018-3/

2 Likes

I would seriously watch out with

public float Health { get; set; } = 1.0f;

If you are using it inside scriptableobject.

Since it looks like ScriptableObject is serializing private variables.
It is going to overwrite your default value.