A Generic C# 3.0 Collection Initialization Adapter
C# 3.0 comes with this new language feature called Collection Initializaton. It’s more or less syntactical sugar that simplifies the way you initialize collections.
Where you pre 3.0 would initialize a list of integers like this:
List<int> list = new List<int>(); list.Add(1); list.Add(2); list.Add(3);
You now can do this:
List<int> list = new List<int>() {1, 2, 3};
Now, this is somewhat beautified, but it does exactly the same as in the first example. The compiler parses the code and calls the Add method, implemented by List<int>, once for every integer in the initialization list.
Now, wouldn’t this be nice to do on your own proprietary collections? Ofcourse. All that’s needed is for your collection to implement the IEnumerable inteface (for uncertain reasons) and add your own Add function:
public class Person
{
public string Name;
}
public class Family : System.Collections.IEnumerable
{
List<Person> members;
public Family()
{
this.members = new List<Person>();
}
public void Add(Person member)
{
members.Add(member);
}
// IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{ throw new NotImplementedException(); }
}
Then you can initialize a family instance like this:
Family family = new Family()
{
new Person() { Name = "Petter" }
new Person() { Name = "Kristine" }
};
It’s that simple. Anyway, in my opinion there is just one problem. You don’t always want to garble your collection with additional interfaces and/or methods just to achieve custom collection initialization. Or maybe you cannot change your collection.
So what is the solution?
Well, one solution is to use the adaptor pattern (or maybe it’s actually the factory pattern) and implement the necessary logic in a seperate adaptor class, then use implicit casting to turn this adaptor class into your target collection. Something like this:
abstract class CollectionInitializationAdapter<F,T>
: System.Collections.IEnumerable where F:new()
{
protected F collection;
// Default constructor
public CollectionInitializationAdapter()
{
// Create new instance of target collection
this.collection = new F();
}
// Abstract and implemented by user to fit the target collection
abstract public void Add(T item);
// Allows implicit cast to type F (target collection)
public static implicit operator F(CollectionInitializationAdapter<F, T> f)
{
return f.collection;
}
// IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
Now, to use this abstract generic adaptor class you need to implement it to fit your proprietary collection. That is, implement the Add function:
class FamilyInitializator : CollectionInitializationAdapter<Family, Person>
{
public override void Add(Person item)
{
// add the item (person) to the target collections (family) members list
collection.Member.Add(item);
}
}
And then put it to use:
Family family = new FamilyInitializator ()
{
new Person() { Name = "Petter" },
new Person() { Name = "Kristine" }
};
Wee! Now you got collection initialization for the Family class (or any collection) without adding any interface or changing any code in the collection itself.
- petter












