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?