brain dust

The Absolute.

Monday, December 20, 2004

C# overloading collection class indexers

I often use a pattern where I inherit my class from the System.Collection class often. This gives me a container to store individual like objects. Here's a short example:


using System;
using System.Collections;
using System.Web;
using System.Text;
using System.Text.RegularExpressions;
namespace InteleReport
{
public class Parameters : CollectionBase
{
public Parameters ()
{
HttpContext c = HttpContext.Current;
for(int i=0;i {
string[] key = Regex.Split(c.Request.QueryString.GetKey(i), "");
string val = c.Request.QueryString[i].ToString();
if(key[0].IndexOf("param")>-1)
{
Parameter p = new Parameter(key[1], val);
this.Add(p);
}
}
}
public void Add(Parameter p)
{
List.Add(p);
}
public void Remove(Parameter p)
{
List.Remove(p);
}
public Parameter this[int index]
{
get{return (Parameter)List[index];}
}
public class Parameter
{
string _Name;
string _Value;
public Parameter (string mName, string mValue)
{
Name = mName;
Value = mValue;
}
public string Name
{
get { return _Name;}
set { _Name = value; }
}
public string Value
{
get { return _Value;}
set { _Value = value; }
}

}
}
}

This gives me a class (Parameters) that I can now bind to a control. Please note that it does not support any sort at all. Sort is not a required implementation of the Collection class, and I don't use it enough to really deal with it here.

Notice that there is one public property called "this". Its construction is different than a normal property because it is an indexer. In the above state it only provides access to objects in the collection through the objects index, or location, in the collection. This is great if you always want to iterate through the collection to find items, or just bind the object to a control.

However, you can also overload the indexer to give it a somewhat more meaningful interface. The catch here is that by doing that you could loose the uniqueness of your object. In some instances that may be ok.

An overloaded indexer could look like this:


public Parameter this[string name]
{
get{
Parameter p = null;//created as null because we don't want to return a new version if we don't find anything
foreach(Parameter pa in this)
{
if(pa.Key.ToLower()==name.ToLower())
p = pa;
}
return p;
}
}

You can have as many overloaded versions of the indexer as you want, but as with overloading in the framework, the signature has to be different based on the type.

The reason that in some cases you might loose your uniqueness is you might have the part of the object you are looking for appear more than once in the collection. In this case however, the keys will be unique so for me it's ok.

This allows you to build a collection and then get an item out of it without having to rewrite a loop through the collection each time (even though that's actually what it does on the back end):

Parameters params = new Parameters();
Parameter hascalled = params["hascalled"];
if(hascalled==null)
throw new Exception("she has not called yet!");

0 Comments:

Post a Comment

<< Home