Share via


Properties? Not my bag, baby.

Eric recently posted a blog: “Property or backing store from inside a class?”, and I responded in a way that skirted the issue entirely. I want to discuss them in a little more detail.

Part 1: Why bother?

First, why do we use properties? The most common answer I hear is “future-proofing”. Specifically, people are concerned that they may need to change the behavior of a property, and don’t want to break existing consumers.

I understand the concern, but I don’t subscribe to the practice 100%:

  • YAGNI – Most of the properties I write, I won’t need. They just go to waste. It’s PrematureGeneralization.
  • I’ll probably build some other part of my API in a way that I have to break the contract when I update, so the properties won’t help.
  • If my class has default accessibility (internal), then it’s trivial to recompile every consumer, so no future proofing is necessary.
  • It takes a simple idea (a field in a class) and makes it take 6 lines. This clutters my code.
  • It’s not the Simplest Thing That Could Possibly Work.

If you’re a library vendor, things are a bit different. You’re selling upgradeability, as well as functionality.

Most of this is inspired by a blurb in Ron Jeffries’ article, Adventures in C#: Contiguous Owners , at the very bottom of the document. He, in turn, was inspired by Ward Cunningham.

Part 2: a simple approach

Just use public fields.

Wait, doesn’t that violate Encapsulation? Only a little bit. If you say “I have a public property call Foo, and its type is int”, that’s not much different than “I have a public field call Foo, and its type is int”. What are you encapsulating, exactly?

Wait, doesn’t that open a risk that someone might set the value, when they shouldn’t? Yeah, but it doesn’t scare me much. I rarely find myself writing code that manipulates the values in other objects. It’s bad behavior on my part, and rarely necessary. If it does happen, and it’s a problem later, I will fix it then.

Wait, I’m still worried about rogue setters. Fine, use ‘readonly’. I do:

        public readonly int Foo; // note that it's named like a property.

        public C(int foo)

        {

            this.Foo = foo;

        }

Now Foo acts like a property with only a getter, and has the same syntax. If, someday, I decide it needs to be a property, I don’t have to modify my consumers. (I do have to rebuild them if they’re in a different assembly.)

I now don’t have to worry about accidentally changing a value, even in my own code.

Also, I’ve noticed a certain pattern. Typically my fields are either “identity of the class” or “working data of the class”. I can see which is which by marking the “identity” fields readonly.

Part 3: lazy load

Sometimes you want to calculate something on-demand, and then cache the value. For example, you might write:

    class Size

    {

        public readonly uint Width;

        public readonly uint Height;

        bool _haveCalculatedArea = false;

        uint _area;

        public Size(uint width, uint height)

        {

            this.Width = width;

            this.Height = height;

        }

        public uint Area

        {

            get

            {

                if (!this._haveCalculatedArea)

                {

                    this._area = this.Height * this.Width;

                    this._haveCalculatedArea = true;

                }

                return this._area;

            }

        }

If you take this approach, you now need to be careful to use the property inside your class, to work with the correct semantics.

I had said I would extract a new class encapsulate this behavior. Here’s what that might look like:

    class Size

    {

        public readonly uint Width;

        public readonly uint Height;

        public readonly LazyArea Area;

        public Size(uint width, uint height)

        {

            this.Width = width;

            this.Height = height;

            this.Area = new LazyArea(this);

        }

    }

    class LazyArea

    {

        readonly Size _size;

        bool _haveCalculated = false;

        uint _value;

        public LazyArea(Size size) { this._size = size; }

        public uint Value

        {

            get

            {

                if (!this._haveCalculated)

                {

                    this._value = this._size.Height * this._size.Width;

                    this._haveCalculated = true;

                }

                return this._value;

            }

        }

    }

Note: I’m violating the Law of Demeter by exposing the Area as public. Consumers must use “mySize.Area.Value”. I think I should probably make it private, and use a public field:

        readonly LazyArea _area;

        public uint Area { get { return this._area.Value; } }

Part 4: Lazy<T>

I’m thinking I could write a generic class to implement this type of caching in a general way. Do you want to take a stab at it, and post your result in a comment or on your own blog?

Comments

  • Anonymous
    April 29, 2004
    I've been thinking that public fields are the way to go over properties. My only problem with the readonly approach is that it makes the field readonly for code both outside and within the class. While I know there are cases where you can initialize a variable once and never change its value again, there are also times when members of the class need to change the value, while code outside of the class shouldn't be allowed to. Sadly, the readonly approach doesn't work in this case.

  • Anonymous
    April 29, 2004
    When you find yourself considering a property, try asking if there's a refactoring to be done. See if putting the field + property behavior into a new class could make sense.

    Properties aren't useless; there are times when they're exactly what you want. But I think they're overused today, to the detriment of code clarity.

  • Anonymous
    April 29, 2004
    Food for thought, certainly. However, public fields don't fit the bill for my needs. Data validation and security checks are common things I use in my properties.

  • Anonymous
    April 29, 2004
    Sean: In your situation, does creating a class to handle the validation and security make sense? Does it make cleaner, more OO code?

    (At this stage in my live, I'm in the more OO=better. I'm sure I'll swing back sometime.)

  • Anonymous
    April 29, 2004
    Binding expects properties, not fields.

  • Anonymous
    April 29, 2004
    I posted a lazy load class on my blog.
    I'm still downloading the technology preview so I haven't checked the syntax yet, but it communicates the overall idea, and it should work.

  • Anonymous
    April 29, 2004
    The WYSYG editor ended up interpreting all my "<T>"'s at tags. I had to switch to html view and then change escape out the "<" and the ">" and the corrected the problem. You should be able to view the correct code now.

  • Anonymous
    April 29, 2004
    The comment has been removed

  • Anonymous
    April 29, 2004
    Paul mentioned this, but there are things to consider when deciding to use properties vs. public fields (as Jay also mentioned in the post). For example, if you choose to use public fields instead of properties then you better make sure that you'd never want to bind the object since you won't be able to unless you use properties.

  • Anonymous
    April 30, 2004
    The comment has been removed

  • Anonymous
    April 30, 2004
    The comment has been removed

  • Anonymous
    April 30, 2004
    jaybaz said: "Wait, doesn’t that open a risk that someone might set the value, when they shouldn’t? Yeah, but it doesn’t scare me much. I rarely find myself writing code that manipulates the values in other objects. It’s bad behavior on my part, and rarely necessary. If it does happen, and it’s a problem later, I will fix it then."


    In my book, that's a potential problem. Its better to code defensively than to take the attitude of "I'll fix it later". I rarely expose a public field because more often than not, I end up needing to use properties for various reasons (granted, I usually write libraries and frameworks so perhaps we are in a different boat).

    I tend to think more futuristically and if I can foresee a potential expansion of its use, I'll code appropriately. What do I do in those cases where I write all these properties and all they will ever do is wrap a variable that may just as well have been a public field? I write the property anyway. I personally, prefer to use properties anyway. However, I do often expose readonly properties and they have their use there, as well.

    I typically use the properties internally as much as I would externally. There are only a few instances where I operate directly on the field. Especially if my class might be inheritied, all the more I use the properties rather than the private members (unless there is a good reason and sometimes there is, but it is the exception rather than the rule).

    Thanks,
    Shawn

  • Anonymous
    May 03, 2004
    Chris says "I write a lot of class libraries and you seem not to that I look at things this way".

    My stated approach is that I'm always writing class libraries. Even when my final goal is an application, I want to create it by first creating the ideal class library for my application, and then having a very small Main() method.

    If I want to have verification in my setter, of course I won't use a public field.

    But as long as I know I can rebuild all the consumers of the code I write, then I will only create a new property if it actually improves the clarity of my code.

  • Anonymous
    May 06, 2004
    The comment has been removed

  • Anonymous
    May 06, 2004
    Maybe I'm being picky, but I think that caching isn't the goal, it's lazy creation.

    Here's a lazy loader that encapsulate those semantics in a nice, OO way: http://blogs.msdn.com/jaybaz_ms/archive/2004/04/30/124229.aspx

  • Anonymous
    May 07, 2004
    http://www.geocities.com/csharpfaq/properties.html

  • Anonymous
    May 07, 2004
    Hmm, I think the article you pointed to is a bit inflamatory. For example, the reasons stated to never use structs are mitigated if you only use immutable structs.

  • Anonymous
    June 15, 2004
    I've been using fields as properties since day one.

    In an in-house project, where your team controls all the code, its easy to do.

    You can upgrade a field to a property late ron, if you need additional code wrapped around the get/set later on.

    Java can not do it. You eithe rhave the choice of public fields, or get/set methods, which means modifying all consumer code - PITA.

    C# allows you to upgrade fields on a case-by-case basis. As jaybaz points out, a public readonly field is effectively the same as a get property (Except you have to init the field at construction time...)

    Its just a nice path.. all public fields, save code.. upgrade necessary fields to properties as required... repeat.

  • Anonymous
    July 12, 2004
    Funny, my feeling has always been that properties were one of the best things added to OOP since its early days.

    >> It takes a simple idea (a field in a class) and makes it take 6 lines. This clutters my code.

    That's because C# was not implemented to streamline the definition of properties. If it was, this wouldn't be an issue. So I say don't confuse concept with implementation.

    However, I think one of the biggest problems is that Microsoft chose to implement fields as having different signatures than properties (ugh!) If you could define a field and later change to a property w/o affecting clients, there would be no need to define a property prematurely and use 6 lines of code when one would do.

    So, I think the designers of C# (and VB) caused this problem. And please don't say that fields are different than properties for performance reasons because most of the time that doesn't matter, and MS could have defined fields has having something like a "direct" qualifier that would cause them to behave like fields behave today when you someone really needs them to be super fast (but doing so would limit future compatibility w/properties.)

  • Anonymous
    February 08, 2007
    Eric Gunnerson just posted Properties vs public fields redux... It's no secret that I agree with Eric

  • Anonymous
    January 01, 2008
    PingBack from http://movies.247blogging.info/?p=4445

  • Anonymous
    June 08, 2009
    PingBack from http://insomniacuresite.info/story.php?id=1090

  • Anonymous
    June 18, 2009
    PingBack from http://fancyporchswing.info/story.php?id=177