Using properties: to be or not to be ? (advice needed)

Hi!

So, I’m a bit confused… Here is some code:

class SomeClass
{
    public SomeType field1;
    public SomeType field2;
    ...
    public SomeType fieldN;
}

And another one:

class SomeClass
{
    public SomeType field1 { get; set; }
    public SomeType field2 { get; private set; }
    ...
    public SomeType fieldN { get; set; }
}

More flexible, isn’t it ?
However I do not like that code for two reasons:

  • It is less readable, I think.
  • Properties aren’t serializable.

Ok, ok… You can tell that we could make properties to be serializable, for example in a following way:

class SomeClass
{
    [serializedField]
    private SomeType field1, ... fieldN;
    public SomeType Field1
    {
          get { return field1 };
          set { field1 = value};
     }
    public SomeType Field2
    {
          get { return field2 };
          private set { field2 = value};
     }
    ...
}

So you see how simple code at the beginning became big and less readable… However that code could be more flexible and more safe.

So my question is: is it a good practise to use properties in Game Development with Unity ?

Thank you in advance.

It’s how I do it all the time.

I come from a none-game design background in .Net and Java. It’s just the way we always do it. From a long term maintenance perspective it’s easier to deal with and grows with your project better.

This can also pertain to Unity, lets say you create a public field that down the line it turns out you need to do some validation on. So you wrap that field in a property, private up that field. Well… 1 of 2 things happen.

You keep the field name the same, which means the public property is different, which means all the referencing code needs to be updated with the new property name, rather than the private fields name.

You change the field’s name to say something with an underscore in front of it, and the property receives the original name. Now all the code doesn’t have to be updated. BUT, now all your previously created GameObjects have their serialized data buggered, because that data is stored by name of the field, and the name of the field has changed.

Now… you may consider it less readable. But I don’t. I of course organize my code.

[RequireComponent(typeof(SomeOtherComponent))]
public class SomeComponent : MonoBehaviour
{

    #region Fields
  
    [SerializeField()]
    private float _speed;
    [SerializeField()]
    private float _bounce;
  
    [System.NonSerialized()]
    private SomeOtherComponent _comp;
  
    #endregion
  
    #region CONSTRUCTOR
  
    void Awake()
    {
        _comp = this.GetComponent<SomeOtherComponent>();
    }
  
    #endregion

    #region Properties
  
    public float Speed
    {
        get { return _speed; }
        set { _speed = value; }
    }
  
    public float Bounce
    {
        get { return _bounce; }
        //no setter
    }
  
    #endregion
  
}

Note - in most IDE’s regions and properties can be collapsed to hide away or short hand all its implementation. Which also increases readability.

Now of course. This isn’t necessary. And a lot of classes that I write that are very adhoc don’t get this treatment, as I just slap out the adhoc script and move on.

But when I’m writing nice clean structured code that is intended to be extensible and reused. Say, stuff I put in my SpacepuppyFramework (open portion of it: GitHub - lordofduct/spacepuppy-unity-framework: This framework is considered obsolete, please see new version at:), it ALWAYS gets this treatment.

2 Likes

One of the basic principles of OOP says that you should hide internal state of objects. So the right way is to use private fields and public props, but all depends on your project - for pet-project it does not matters, but for big one is is impotand to cone in right way.

Thank you for having time to answer me! Great answer! I’ll look through the framework you shared.

I am just afraid that my code will look less readable and the code size will increase. Of course it will depend on the application you write. I haven’t got enough experience in Unity development so I stayed the principle “keep it simple” until I met the code of another developer who (in my opinion) write his programs may be very safe and strong but unreadable for others…

Yes… It depends. ) What if you do not know how big would be your project ? )

These guidelines provide optimal ease of use in Unity regardless of access modifiers for the field or property:

  • Start with properties instead of fields, with only the necessary get/set options.
  • Turn a property into a field if all it would consist of is {get; set;} (think of the ; as a shortcut for {get; set;}), unless it requires serialization. PascalCase will be used for a field, until it needs to be serialized.
  • When a field becomes serialized, treat it as a backing field for a property. Create that property at the same time as adding [SerializeField].
  • Use camelCase for all backing fields, serialized or not.
  • Do not use backing fields directly, outside of property blocks. The this keyword should rarely be needed, as local variables will be camelCase, and class members will be PascalCase.

Also, don’t use the private modifier when it is useless. Useless is synonymous in this case with “only useful to someone who doesn’t know the default access modifiers of the language”. That person won’t be knowledgeable enough to make good use of the guidelines. Teach them.

[SerializedField] SomeClass someClass1; public SomeClass SomeClass1 {
    get {return someClass1;} set {someClass1 = value;}
}

[SerializedField] SomeClass someClass2; public SomeClass SomeClass2 {
    get {return someClass2;} private set {someClass2 = value;}
}
1 Like

So, size of your project will depend on your codestyle )
Using right techniques you can write a big project as well as a small, but otherwise you can create only small.

My point - use public properties for data that should be accessible outside of class, use private fields with SerializedField attr for showing data in Inspector, and hide internal state and implementation as much as you can.

Also don’t forget about testing and think before doing )

1 Like

Thanks for the great tip!
About the useless private modifiers: they are some kind of protection: not to give someone to modify something if there some other way (defined by developer) to do that.

Cheers!

Got it! Thank you very much!

As I alluded to in my post, private is the default, so I don’t believe it’s ever needed for fields & properties. There may be some edge case I’m not thinking of.

Got it. Thank you!

Hm… There is a difference between:
public SomeType SomePropertyName { get; private set; }
and
public SomeType SomePropertyName { get; }

With latter you can’t make set even if you do that in containing class.

Really? Sounds very strange. What should property return, if no one can set it? Maybe in this case it will work like a readonly fields - when we can make set only in constructor of class?

class MyClass
{
   public SomeType SomePropertyName { get; }

   public MyClass() {
       SomePropertyName = new SomeType(); /// work
   }
   public void SomeFoo Method() {
       SomePropertyName = new SomeType(); /// don't work
   }
}

Or this property will not compile… Need to try : )[/CODE]

I use properties all the time, when I need to track changes or when I “convert” it into a properly serializable format.

I just need to add [Inspect] to my properties for them to show up on the Inspector, so it’s rather easy. (See Advanced Inspector for mode detail)

Frankly, properties are just too useful to ignore.

Properties with private accessibility for one accessor is a case where private is not useless. private is useless if both accessors have the same accessibility.
public SomeType SomePropertyName {get;} won’t compile yet, but C# 6.0 allows get-only automatic properties, if they are assigned inline. I don’t think you can set them in the constructor, which would make them a full replacement for readonly fields. Personally, I see no point in not just using a readonly field.

Not, it’s useful. Example;

        [SerializeField]
        private string assemblyQualifiedName = "";
   
        public Type MyType
        {
            get { return Type.GetType(assemblyQualifiedName); }
            set { assemblyQualifiedName = value.AssemblyQualifiedName; }
        }

Unless you’re talking about only implicit properties?

I don’t understand why you don’t think that private is useless.

I also don’t understand that question. You might mean “automatic” by “implicit”, but I still don’t get it if so.

Edit: Okay, I think you thought my “It” wasn’t a pronoun. It was, so I changed it to not be, for clarity.

“It” meant “Properties with private accessibility”? That’s quite a stretch! :stuck_out_tongue:

Auto-implemented properties are also called “implicit”, because the other way around is when you “explicitly” declare a backing field. If you google “implicit properties”, it knows exactly what it means. :wink:

No, just private. That is, the keyword, not the concept of what it does. I changed the post.