Introduction
This an attempt to offer an alternative to the generic KeyedCollection
for ease of use.
Background
I'm a fan of the KeyedCollection
. Simply because, in a simple way, it resembles how a table in a database works. The objects in the KeyedCollection
contain their key values. This makes it a good candidate for caching and handling business data in memory in a database-like manner.
However, a few thing are annoying when dealing with the KeyedCollection:
- It's
abstract
, so you'll have to make an implementation to use it. - Unlike tables from a database, you can use only one value as your key.
The primary objective
The primary objective of the KeyedList
project is to make a more easy-to-use version of the Generic KeyedCollection
, that can be used like this:
KeyedList<string, MyClass> list = new KeyedList<string, MyClass>();
if(list.Contains("key"))
{
MyClass item = list["key"];
}
Using the code
The KeyedCollection
is abstract
, and requires an implementation to work; more specifically, you'll have to implement a method GetKeyForItem()
that will provide a key for the KeyedCollection
for the items in the list.
The KeyedList
is, in fact, an implementation of the KeyedCollection
, but it offers three alternate ways to let the user provide keys for the chosen item.
- By passing in a delegate on instantiation:
KeyedList<string, MyClass> list =
new KeyedList<string, MyClass>(x => x.KeyValue);
KeyedList<string, MyClass> list =
new KeyedList<string, MyClass>( delegate(MyClass x){ return x.Keyvalue; } );
- Implementing an interface on the target class:
class MyClass : IKeyedItem<string>
{
string IKeyedItem<string>.Key
{
get { return this.KeyValue; }
}
}
KeyedList<string, MyClass> list = new KeyedList<string, MyClass>();
- Or finally, by decorating the "
Key
" property with a DataObjectField
attribute:
class MyClass : IKeyedItem<string>
{
[DataObjectField(true)]
public string KeyValue { get; set; }
}
KeyedList<string, MyClass> list = new KeyedList<string, MyClass>();
When the key is a combination of values
Then what? Today's Dictionary
s and KeyedCollection
s do not offer a straightforward solution. Let's imagine we have a table that holds order lines... the key would usually be a combination of an OrderId
and a LineNumber
. The key is only unique when you combine these values. How do you represent that structure using a Dictionary
to enforce the uniqueness?
KeyedList<int, string, MyClass> list = new KeyedList<int, string, MyClass>();
if(list.Contains(2, "key"))
{
MyClass item = list[2,"key"];
}
I have a suggestion on how to resolve this issue. By using a lightweight generic structure to hold the values as if they were one, and at the same time, providing its own comparer for the Dictionary
.
public struct Key<T1, T2> : IEquatable<Key<T1, T2>>
{
public Key(T1 value1, T2 value2)
{
}
}
class KeyEqualityComparer<T1, T2> : EqualityComparer<Key<T1, T2>>
{
}
You can actually use it directly with a normal Dictionary
, like this:
Dictionary<Key<int, int>, MyClass> dictionary =
new Dictionary<Key<int, int>, MyClass>(Key<int, int>.Comparer);
MyClass item = dictionary[new Key(123, 456)];
However, I find it more elegant and easy to use to have it embedded directly in the KeyedList
itself.
If you have inputs or feel like adding, correcting, or improve the code, please join the project at Codeplex.
Points of interest
I find that caching more and more data in a more and more complex form seems to be a trend. For that reason, I applaud whenever new and interesting methods and technologies that make this easier comes along... first, the anonymous methods, and later, Lambda expressions and LINQ for Objects. However, I always prefer simple objects over ADO DataSet
s and DataTable
s to hold my data in memory; they are simply too heavy and too slow if your data reaches certain amounts. So, out of necessity, I made this implementation.
History
None so far.
Software designer/developer with specialization in distributed applications, E-commerce and MS Dynamics Integration using Microsoft .NET Technologies.
Software Design and Development since 1999.
.NET since 2001