Saturday, May 14, 2005

On properties and events

The simplest way to declare an event in C#, only requires from you to provide the event declaration:
event EventHandler Click;
Then, the C# compiler adds the implementation:
  1. A private field of the corresponding delegate type.
  2. A method called add_Click for adding handlers to the delegate chain.
  3. A symmetric remove_Click method, for removing handlers.
Outside the declaring class, the only operations you can perform with the event is adding and removing event handlers, using the now famous shortcut:
myClass.Click += myClickHandler;
By the way, you can’t fire the event from outside the declaring class! That’s encapsulation. However, things are different inside the class. The compiler generates a private field, and it doesn’t let you access that field... apparently. Actually, whenever you mention the event identifier from inside the declaring class, the compiler handles the identifier as if it were the private field. You’re free to do with the event identifier whatever it’s allowed with a delegate type field.
Events in Freya are identical to C# events. We also implemented a variant of this trick to be used with properties (credits belong to the authors of Chrome, another .NET language inspired in Delphi). When you’re designing a class, you often declare fields that should be transformed later into properties… or, on the contrary, you start with properties that map directly to a naked field with the same type. How much code do you need to write in this very simple and frequent case? A lot, if you’re using C#. You must declare the field, then the property and most of the times, both access methods.
In Freya, you only need to declare the property:
property Caption: string;
If we don’t provide an implementation for Caption, Freya will generate a private field and two access methods with proper signatures. Outside the declaring class, you will only see the property. However, inside the class, any reference to the property will be translated as a reference to the underlying field. In our previous example, Caption is a read/write property. If you want a read only property, you only need to add the readonly keyword to the declaration:
property Caption: string; readonly;
You could even declare an initializer for the property:
property Caption: string := 'Form1';
That’s an internal access, of course, and the compiler just moves the initializer to the private field. Of course, you can also “initialize a property” when the property has an explicit setter, but then, the initialization code calls the setter method when creating a new object instance.
As a final remark, we allow grouping related properties in a single declaration:
property X, Y: Double := 0;
The initializer applies to both properties, of course, and it should be evaluated only once.

Labels: , ,


Post a Comment

<< Home