Share via


Properties as objects

I was thinking about two items from Object Thinking:

  1. Everything is an object.
  2. Every object should provide events for when its attributes change.

There's the idea that objects can collaborate without top-down control, if they provide & register events with each other.

My first reaction to #2 is that it violates YAGNI. But in the interest of extremism, I'll let it ride for now.

The standard way to do #2 is something like:

      class Customer

      {

            int _age;

            public int Age

            {

                  get {

                        return this._age;

                  }

                  private set

                  {

                        this._age = value;

                        this.Age_OnChange(this, null);

                  }

            }

            public event System.EventHandler Age_OnChange;

      }

Now, you already know how much I love properties. I’m annoyed when I read this code, because I use 15 lines of text to express what should be a very basic idea.

There’s also a bunch of smelly duplication. Not only does the word “age” appear 6 times, but 2 of them are carefully concealed in a bigger name (“Age_OnChange”), which is quite easy to miss in later code changes. Yuck.

So, what if we apply #1? What if we make an object that represents a property? It would look like:

      class Property<T>

      {

            public Property(T t) { ... }

            public event System.EventHandler OnChanged;

            public T Value { ... }

      }

Well, I tried to implement it, and ran into some problems. The biggest is that I can’t state who has permissions to set the property. With the seed code above, only the containing class has write access to the value.

Here’s the best I came up with:

      class Property<T>

      {

            private T _value;

            public event System.EventHandler OnChanged;

            public T Value

            {

                  get { return this._value; }

                  set

                  {

                        this._value = value;

                        this.OnChanged(this, null);

                  }

            }

      }

      class Customer

      {

            public Property<int> age = new Property<int>();

            static void Main(string[] args)

            {

                  Customer customer = new Customer();

                  customer.age.OnChanged += delegate { Console.WriteLine("age changed"); };

                  customer.age.Value = 9;

            }

      }

I don’t think I can do any better. Got any ideas?