Question

I'm in the process of trying to create a collection that will only contain one element per type. Each of the types will have to subclass a root type however, so that there is a commonality. I've done some research and am wondering if I'm on the right track here or if there are some improvements that can be made:

class TypedList<T> : Dictionary<Type, T> {

    public override void Add<C>(T instanceOfType) {
        base.Add(typeof(C), instanceOfType);
    }

}

Specific questions:

  • Is this the correct/best approach?
  • What should I do to facilitate retrieving elements?
  • If the Add() method is correct, is there any way to enforce that C is a subclass of T?

Updated code to reflect Ondrej's suggestions:

class TypedList<Abstract> : IList<Abstract> {

    protected Dictionary<Type, Abstract> data;

    public void TypedList() {
        data = new Dictionary<Type, Abstract>();
    }

    public void Add<Concrete>(Concrete instanceOfType) where Concrete : Abstract {
        data.Add(typeof(Concrete), instanceOfType);
    }

} 
Was it helpful?

Solution 3

Many months later and I think I've come up with a really nice solution, which is to use a collection I wasn't aware of initially KeyedCollection:

public class TypedSet<AbstractType> : KeyedCollection<Type, AbstractType> {

    protected override Type GetKeyForItem(AbstractType item) {
        return item.GetType();
    }

}

Very conscice and doesn't require any stitching of different types of collection classes together. Makes for slightly more idiomatic code as well as KeyedCollection is abstract and requires implementation of GetKeyForItem.

OTHER TIPS

This should give you the constraint you're looking for!

class TypedList : Dictionary {

public override void Add<C>(T instanceOfType) where C : T{
    base.Add(typeof(C), instanceOfType);
}

}

However, I'm wondering why you're not just using a dictionary straight up? I.E. the dictionary that you're subclassing should behave the way you waint?

The approach generally seems fine. However, I'd consider hiding the Dictionary<Type, T> as a private field and reimplementing the interface you want. It needs not to be IDictionary<Type, T>, it may as well be just a IList<T>.

Another option is to use List<T> for internal storage, and HashSet<Type> to maintain the set of types of items in the list. Such underlying storage may be better suited in case IList<T> is the wanted interface of TypedList<T>, solving the “missing index” problem with a dictionary.

Also, the Add<C> method declaration seems incorrect. You should declare it as:

public override void Add<C>(C instanceOfType) where C : T {
    base.Add(typeof(C), instanceOfType);
}

That makes sure C will be an ancestor of T. In your original declaration C could have been any type, possibly unrelated to T.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top