Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Should I switch to using get/set methods instead of properties

Discussion in 'General Discussion' started by Luemus, Jul 21, 2022.

  1. Luemus

    Luemus

    Joined:
    May 20, 2013
    Posts:
    103
    I've seen some posts/books suggesting that properties should be avoided, and that made me realize that I am using properties way too much. I know that they generate backing fields at the compile time. Should I switch to using get/set methods with private fields?
     
  2. BIGTIMEMASTER

    BIGTIMEMASTER

    Joined:
    Jun 1, 2017
    Posts:
    5,181
    i've wondered the same thing.
     
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,191
  4. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,010
    Why properties should be avoided ?
    I think they are great.

    And I would say it is other way around, Properties were invented so you no longer have to use get/set methods.
     
    Shushustorm, NotaNaN, andyz and 2 others like this.
  5. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    No.

    Properties already are syntaxic sugar for get/set methods. And compared to properties, get/set are WAY more verbose.

    When you receive a programming advice, you need to ask yourself a question: "what do I get from following this advice?". If you can't answer, then do not follow that advice.

    Blindly following recommendations leads to creation of cargo cults. You should question the advice received, and do not blindly believe.
     
  6. BIGTIMEMASTER

    BIGTIMEMASTER

    Joined:
    Jun 1, 2017
    Posts:
    5,181
    or you might just not understand something, so you ask for clarification.

    what are you talking about here? Guy is not asking for advice on how to read and critically think. He is asking if there is something to the use of get/set methods because he can't tell a difference. That doesn't mean there is not one.
     
  7. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    Properties are functionally exactly the same as getters/setters.

    For Unity development specifically, the typical argument is not "replace properties with getters/setters", but "reference fields instead of properties".

    The reason being that accessing a field is technically faster than accessing a property, because the latter is an implicit method call.
    Code (CSharp):
    1. public int myIntField;
    2. public int MyIntAutoProperty { get; set; }
    3.  
    4. ...
    5.  
    6. // Get value directly from field.
    7. int fieldAccess = myIntField;
    8.  
    9. // Get value from implicit method call to backing field.
    10. int propertyAccess = MyIntAutoProperty;
    But honestly, it's a micro-optimization and really not a big deal.
     
    Neopy, Luemus and BIGTIMEMASTER like this.
  8. Luemus

    Luemus

    Joined:
    May 20, 2013
    Posts:
    103
    Well, I wouldn't create this post if I were to blindly follow other people's advices. I see no benefits of using get/set and just asked if there is anything that I missed or maybe an edge case for Unity.
     
    NotaNaN, hippocoder and angrypenguin like this.
  9. koirat

    koirat

    Joined:
    Jul 7, 2012
    Posts:
    2,010
    Pure property ( {get;set;} ) will be as fast to access as a field.

    Property encapsulates get;set; and this might be useful when using reflection.
    Property can raise some event when changing value. Field cannot.
    Property can have different privilege for setting and getting. Field cannot.

    It's easier to refactor field to Property than to set/get.

    Filed can be used with ref out. Property cannot.

    We cannot access single field of structure via property.

    Property is better with intellisense than set/get method
     
    Last edited: Jul 21, 2022
    Luemus likes this.
  10. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    You mean auto-properties like
    public int CustomerId { get; set; }
    ? If so, it's not really different compared to
    public int CustomerId { get => m_customerId; set => m_customerId = value; }
    in terms of execution speed or readability, but does have the advantage of allowing you to add breakpoints, logging, validation, etc to the get/set methods if needed.

    Personally I think the issue with properties is that since they look the same as fields from the outside they give the impression they are "cheap" to read/write like fields are, but being actual methods they could have some all sorts of CPU-intensive, side-effect causing, GC alloc-prone logic behind them which can bite you if you end up using them in "hot" code.

    Some examples are Unity's
    Renderer.material
    (which creates a copy of the sharedMaterial object when accessed for the first time, which can leak memory if you never call Resources.UnloadUnusedAssets or do a non-additive scene load) and
    GameObject.tag
    (which allocates a new string every time you read it).

    So I prefer using actual methods over properties if the work behind them is significant enough.

    Also, sometimes when you're deep into optimizing hot code "dumb" properties can be a problem for accessing complex structs, since they return a copy of the struct. Fortunately, nowadays
    readonly ref
    is a thing, and you can have properties return that instead of a copy of a struct if you have a situation where it isn't really possible to revert to a plain field.
     
    d3eds, DungDajHjep and Luemus like this.
  11. SunnySunshine

    SunnySunshine

    Joined:
    May 18, 2009
    Posts:
    958
    I tend to only use properties if I want to make something publicly readable but not modifiable. For most other things, when it comes to objects communicating with each other, I tend to use methods. It's very rare I need to set a variable in another object directly unless during initialization. If you're very reliant on setting properties in another object frequently, you may be doing something wrong and making the code too coupled. It shouldn't be the responsibility of an object to set the properties of another object. Rather, some event can be communicated to the object which causes it to refresh some private property.

    But, it all depends on the situation of course. If it is some very high performance code in a physics system or something, even changing fields directly may be justifiable since that is much faster to do than run methods.

    In the end, the important thing is that the code is readable and maintainable. And the more interdependence you have in your project, the harder it will be to maintain.
     
    Last edited: Jul 21, 2022
  12. grizzly

    grizzly

    Joined:
    Dec 5, 2012
    Posts:
    356
    For trivial properties the compiler's smart enough to inline them so there's no additional overhead. Properties are a tool of the language. Their pros and cons are explained above. Use them if required.
     
    Luemus likes this.
  13. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,004
    This is a pretty common pattern in my code these days, mostly because it makes thing quick to set up:

    Code (CSharp):
    1. [field: SerializeField]
    2. public int SomeInt { get; private set; }
    Does have some issues in certain fringe cases, such as when using fancy stuff like Odin Inspector's AttributeProcessors, but that only comes up now and again.

    Though if I'm specifically returning copies of reference types I prefer to use an explicit method. Same with setting values that requires more than a simple assignment.
     
  14. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    505
    I think OP should clarify what books in what context said that properties should be avoided.
     
    RecursiveFrog likes this.
  15. Luemus

    Luemus

    Joined:
    May 20, 2013
    Posts:
    103
    It's in Jeffrey Richter's CLR via C# book. He gives some examples in the book and why he dislikes them. Check this StackOverflow thread for a bit more detailed look on the books claims.
     
    DragonCoder likes this.
  16. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    I use properties because "when in Rome, do as the Romans do". But I dislike them in principle and believe that get/set methods are superior.

    Mainly, this is because a property is dedigned to obfuscate the fact that there's a get/set method call, and instead look like a variable is being accessed, which is just hiding important information from the coder (with the usual excuse bring "the IDE will tell you") or, worse, trusting that info to be communicated by convention (which is not reliably followed, see: Unity's own API).

    That personal opinion aside, a property is a method, so there is no functional difference in the resulting program. From just a quick skim, the SO list's arguments either boil down to what I said above, or make assumptions about what's best, e.g. that all properties "should" have both get and set (which I fundamentally disagree with, it's a silly generalisation to be making).

    In short, as long as you're aware that property use = a method call and take it into account on the rare occasions where it matters, go ahead and use them. I pretty much just consider them to be a language quirk, personally.

    Edit: They do have a neat functionality as a result of being syntactically identical to a field when used. You can replace a field with a property and change how it behaves, such as adding log messages or a break point or an event being raised, without having to modify calling code. This results in mess elsewhere, but has occasionally been useful when investigating / experimenting / making last minute hacks which need to be refactored ASAP.
     
    Luemus, Kreshi, algio_ and 1 other person like this.
  17. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    Unity uses C# for scripting. So if you try to learn proper C#, you might end up using practices that you wouldn't want to use in unity. C# pushes for immutability. Immutability incerases number of garbage allocations. And you want to reduce number of garbage allocations in Unity.

    THis could be flipped around, though. If you have getX and setX, it means that there's a variable X or a concept X on that object. And the getters/setters obfuscate that fact by insisting that it does not exist, while it is actually there.

    Either way, this is a matter of taste.
     
    Luemus and Ryiah like this.
  18. algio_

    algio_

    Joined:
    Jul 18, 2019
    Posts:
    87
    In my view every language construct has is pros and cons: properties are useful because of the easing in writing get/set methods so if one is working in an environment of C# only programmers maybe properties don't cause misunderstandings, but in a mixed context I would avoid them because externally they are viewed as normal variables.
    I made this experience when I started with unity (coming from C/C++), I had to write a procedural mesh generator so accessed mesh.vertices every iteration. I understood there was something strange when compiled and started the code, as it was incredibly slow. Then what was a solution (I'm writing it for demonstration purposes, as I don't like it very much)? Writing more code:
    Code (CSharp):
    1. var vertices=mesh.vertices;
    2. iterate handle vertex stuff...
    3. mesh.vertices=vertices;
    This has to be done for every property mesh.colors, mesh.normals etc. However I must say that if one needs to hide internal class functionality or write hundreds of get/set methods, properties are kind of a solution but one doesn't have to like it ahahah
     
    angrypenguin and Ryiah like this.
  19. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    This is not really property's fault.

    For example, bitmap/texture related classes often contain "newbie trap" which is.... GetPixel/SetPixel.
     
    Ryiah likes this.
  20. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,184
    C# is first and foremost an object oriented programming language and one of the main principals is to treat classes as black boxes. You are supposed to be treating properties as if they were normal variables.
     
    Last edited: Jul 23, 2022
    algio_ likes this.
  21. algio_

    algio_

    Joined:
    Jul 18, 2019
    Posts:
    87
    I understand you point of view however i believe that if the OP is asking a question about properties he should decide knowing what types of effects that kind of code can have.
     
    Ryiah likes this.
  22. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,184
    Agreed, but your example has something to it that he won't encounter in his own implementation. Unity's various classes like the one you gave as an example don't store their data in C#. They store it in C++ and then marshal it back and forth.

    https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Graphics/Mesh.cs
    https://github.com/Unity-Technologi...ster/Runtime/Export/Graphics/Mesh.bindings.cs
     
    Last edited: Jul 23, 2022
    algio_ likes this.
  23. algio_

    algio_

    Joined:
    Jul 18, 2019
    Posts:
    87
    I suspected there was something going under the hood :) Thanks for linking the source I wish I knew it was available when I started.
    Anyways If the OP or someone reading wants to use marshalling or similar now he can know a bit of what to expect.
     
  24. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    They're equivalent to get/set function calls, although some optimization might take place. In your example, if you used get/set vertices, you'd experienced the exact same thing.

    Meshes and Textures are special resources that live at least partially on GPU. And special care needs to be taken by the engine when they change.
     
  25. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You'll know when you really need them (hint: unless doing a framework or working in a team, you probably don't).

    I have 0 get/set in my codebases after over a decade in Unity, and shipped games. But I can appreciate them being used in libraries, or 3rd party assets or engine code... there's a place for this sort of validation.

    A lot of material out there isn't actually suitable for game dev, and even less suitable for solo game dev. There is a point to using this stuff.

    Just use private properties / variables and no get/set. Use serialize to store inspector values etc. Be less is more.

    Worry much more about the actual code you're doing.
     
    Luemus likes this.
  26. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    I don't see how Get[TheVariableName] or Set[TheVariableName] are at all obfuscating the existence of the variable. They're certainly not "insisting that it does not exist". To the contrary, they are telling you that it does exist, but that you aren't allowed to access it except through them.

    I'm not sure what "this" is in regards to it being a matter of taste, but direct variable access vs. getters/setters (of whatever syntactic presentation) is not just a matter of taste, it's a core part of the "abstraction" part of OO. As a user of an object I shouldn't necessarily have to (or be able to) understand its interior workings, but I should be able to make any valid call to its public interface with confidence that it'll look after its internal state to the greatest extent practical.
     
    algio_, Hikiko66 and hippocoder like this.
  27. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    If it existed, it would've been a single visible entity. Instead there are two entities to interact with a non-existing hidden thing that has a name but not object, field or variable associated with it.

    I do not see OOP as an inherently good thing and I do not see adding getter/setters to everything as a necessary part of the OOP. If your field does not require extra processing when it changes then it should remain a public field and neither have a getter nor be wrapped within a property.

    The point is to hide SOME mechanisms from the users when it is necessary. And not wrap every single public variable.

    From this point of view, thinking about it, properties are better. Because t hey declare a public interface and list what things and concepts you can access through this object. And when a property is marked read/write only that also indicates what you aren't supposed to do with it.
    -------
    Thinking more about it, it goes like this:
    * A field that requires no extra processing, should remain a public field.
    * A field that requires extra processing or has to be readonly but represents a concept should probably be a property.
    * Something that is not actively maintained as a part of the object but can be calculated on request, should be a method.

    For example, we have Vector3. Making its fields properties would be a bad idea and is pointless (There is IntVector which does that, and that results in significant slowdown in profiler). If we want to have a way to set the vector using radial coordinates, that would work best as a method and the method could be static. On other hand Vector3.normalized probably shouldn't be a property, but a method instead, get normalized.

    Things would've been better if C# had a concept of const method. Because a const method indicates you that this method does not change the object. Since const methods do not exist, by default any function call can be altering object's state, which also could be a reason to prefer a property over getter instead.
     
    Last edited: Jul 23, 2022
    Luemus likes this.
  28. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    The first part here seems arbitrary. Does ny computer not exist because it has more than one part?

    And the second is wrong. GetX, in English at least, explicitly assumes the existence of a concrete thing called X which can be retrieved. "Get the apple" explicitly assumes there is an apple to get. Similarly, "set the direction" explicitly assumes that the thing you're referring to has a direction which can be changed.

    As an aside, with methods the name can communicate more than property names typically do as to whether or not something "really" exists, if that's a sticking point for you. "GetX" means that the thing exists and is being accessed. "IsX" checks whether a concept is true, which could be derived rather than stored. "Calc(ulate)X" means that it isn't stored and is calculated on access, and if that's heavy then could maybe benefit from caching in some cases. All of which goes mildly against dogmatic OO - we're meant to ignore implementation details - but in many cases is useful for a calling class's designer to be aware of (see: the Unity API, where accessing some stuff which looks like variables does pretty expensive work internally).

    I didn't say that they need to be used all the time. If a field can be changed at any time to any value with no negative impact on the object's state then simply setting it to public satisfies the requirement I mentioned.

    I am not being dogmatic, I am being practical.
     
  29. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    This doesn't follow, as even a get property can modify state.
     
  30. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    For a human programmer the property marked as read only has semantic implication of method being marked const. It is supposed to return the value and not alter the object. You're not supposed to alter the value. A method called "getX" has significantly weaker implication of not altering objec'ts state.

    In C++ const method is pretty much a guarantee that this method is safe to call and never alters the object, although there's still "mutable" attribute if you want to make your life interesting.
     
  31. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    Nothing done by convention can be trusted.
     
    neoshaman likes this.
  32. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,799
    Switch to public fields. I prefer less ambiguity and basically know what every field should be allowed to do and provision it in code. I have never needed to use a get set on any components or class in Unity but have had to provision them in .dll's for plugins. Avoid interfaces wherever possible. Great enterprise schtick but just causes problems tracing issues, no Inspector fields. I suspect Unity has gotten slower due to the number of Interfaces they add to each package (C# developers may not be the best game engine devs as they bring their enterprise habits into the mix where they DO NOT belong.). Seems like alot of conditional switchboard wiring under the hood to me. I prefer the old school Unity. It compiled fast.
     
    Luemus likes this.
  33. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,266
    I often use public (nonserialized if needed) fields in this case because I'm a vulgarian, but the existence of properties is a huge boon because it lets me add side effects without changing any context. So if I can't figure out why the value of a field is incorrect at runtime, I can temporarily convert it to a property without changing anything else and add a debug log with callstack to trace back the issue.

    I occasionally use getter and setter methods if I need to interface with UnityEvents or I need a delegate that isn't anonymous (like maybe I need to unsubscribe from an event at the end of an object's lifecycle and benefit from having a named method I can reference), but I do dislike the verbosity.

    I occasionally keep properties in situations where the backing field is of a different type (e.g. when storing the value of health as a float for calculations even if it should only ever be set to a whole number, date/time that has a string representation, etc). I also really like them for caching situations: I might have a ScriptableObject that, when first accessed at runtime, generates an instance of itself and thereafter mutates the instance when used; this pattern has cut down on a lot of annoying order-of-operations bugs over the years.

    So it's great to have them as part of the toolbox, IMO.
     
    Luemus, Ryiah and ippdev like this.
  34. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,337
    Uh, have you ever worked with python?
    Python has no constants. Therefore, a convention used. ALL_CAPS variable is to be considered a constant. Nothing stops you from changing it.

    Python also has no access controls for classes (private/protected), meaning all fields and methods are public and it is often possible to add/remove them at runtime. Therefore, a convention is used. Field whose name starts with underscore is to be considered a private field and shouldn't be touched. But nothing stops you from doing that.

    The reasoning is this:
    "There's no equivalent for constants in Python, as the programmer is generally considered intelligent enough to leave a value he wants to stay constant alone"

    If convention cannot be trusted, then you should switch to C++ right now. Becuase it can enforce this stuff, while C# can't.
     
    Ryiah likes this.
  35. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,519
    Yeah, that's a big thing I prefer about C++ over C#. Nothing to do with the topic, though.
     
    algio_, Ryiah and neginfinity like this.