Tuesday, December 5, 2006

A Page On Properties

Whew! Was it two weeks since my last post? Time sure flies fast when you're busy doing interesting things... As for my schedule change, it got a bit chaotic due to unforeseen natural events (typhoons and family events). However, I can say that it's now successful. I did, however, toned down playing basketball from everyday to 4-5 times a week. I find that I can't quite sustain the physical abuse seven mornings a week -- not if I want to spend some time with my wife and son.

I've been re-building my personal code libraries for the past two months, and have been doing well for the most part. Because of this, building some common libraries for work wasn't that much harder. I mostly just break them down to reuseable classes so I don't have to write the same thing more than once -- ok, twice. But along the way, I encountered this weird property thing. In Delphi and C++, it's powerful and straightforward. Turned out it wasn't so simple and/or elegant in C# and VB.

In VB, it kinds looks ugly to use the () pair to index stuff, as opposed to the [] pair I got used to, but I can adapt to a lot of style. What surprised my was that in C#, which I thought was a pretty good language to begin with, does not have an indexed property! Wow! I wasn't quite prepared for that one. I know, I know, you can create a class indexer as this[], but it's not the same thing. What I really wanted was something like this.sublist[] - and, well, it's not built-in. I did find a way around it however, thanks to a bit of google`ing.

For anyone interested at all, what you do is just create some sort of class whose main purpose is to do the indexing. This indexer class gets instantiated inside the host class and will be returned as a regular property. Hmmm, wasn't quite as clear as I wanted to say, so let's have an example.

In my case, I was doing a class to act as a section of an *.ini file (yeah, quaint compared to xml, but it's simpler) and I wanted to be able to do the following at a minimum:

section s = new section(sectionName)
s[keyName] -> returns key=value pair where key=keyName
s[index as int] -> returns key=value pair at position index
s.keys[index as int] -> returns the key at position index
s.values[keyName] -> returns value for keyName
s.values[index as int] -> returns value at position index


In order to support the likes of s.keys[] stuff, I created extra classes to be indexers. Here's how I did it:

public class KeyIndexer
{
public KeyIndexer(section owner)
{
_owner = owner;
}
public string this[int index]
{
// KeyAt() is a function declared in section
get { return _owner.KeyAt(index); }
}
private section _owner;
}


The host object simply declares an instance of this one and returns it whenever the property Keys is accessed. From the host class, this is how it's utilized:

public class section
{
public section(...)
{
...
_ki = new KeyIndexer(this)
...
}
...
public string KeyAt(int index)
{
... code to find and return key value at index ...
}
...
public property Keys as KeyIndexer
{ get { return _ki; } }
...
private KeyIndexer _ki;
}


With this done, you can do things like s.Keys[index] to get the key at index! It's a lot more code that I would have like, but it's what it took to make the client code much more readable. Just like most everyone else I read about, I have no idea why C# do not have indexed properties. It sounds like a major oversight not to have one considering that array-like properties are not that rare.

No comments: