views:

35

answers:

1

In C# I have a bunch of objects all inheriting from the same base class.
I also have a number of Dictionaries, one for each subclass.
What I want to do is add all of those Dictionaries to one List so I can loop through them all and do some work (like comparing the lists etc).

In summary

Dictionary<string, Child> childObjects = new Dictionary<string, Child>();
List<Dictionary<string, Parent>> listOfDictionaries = new List<Dictionary<string, Parent>>();
listOfDictionaries.Add(childObjects);

I would have thought that since Child inherits from Parent, this should work, but it won't compile. Clearly I am not understanding something about inheritance and generics :)

A full code example

class Program
{
    static void Main(string[] args)
    {
        //Creating a Dictionary with a child object in it
        Dictionary<string, Child> childObjects = new Dictionary<string, Child>();
        var child = new Child();
        childObjects.Add(child.id, child);

        //Creating a "parent" Dictionary with a parent and a child object in it
        Dictionary<string, Parent> parentObjects = new Dictionary<string, Parent>();
        parentObjects.Add(child.id, child);
        var parent = new Parent();
        parentObjects.Add(parent.id, parent);

        //Adding both dictionaries to a general list
        List<Dictionary<string, Parent>> listOfDictionaries = new List<Dictionary<string, Parent>>();

        listOfDictionaries.Add(childObjects);  //This line won't compile

        listOfDictionaries.Add(parentObjects);


    }
}

class Parent
{
    public string id { get; set; }
    public Parent()
    {
        this.id = "1";
    }
}

class Child : Parent
{
    public Child()
    {
        this.id = "2";
    }

}

Is there any way of achieving this?

+2  A: 

You can't do this safely. Imagine you did this:

listOfDictionaries[0]["foo"] = new Parent();

That looks fine - but it would mean that childObjects would contain a value which isn't an instance of Child!

C# 4 has introduced restricted generic variance where it's safe - so you can convert a reference of type IEnumerable<Banana> to IEnumerable<Fruit> for example - but what you're wanting to do here isn't safe, so it still isn't allowed.

If you could tell us more about the bigger context - what you're trying to achieve - we may be able to help more. Can you give examples of what you'd want to do with the list afterwards?

Jon Skeet
Thanks Jon, hadn't thought about updating.The context is a comparison tool to compare two sets of meta data. So, I have a list of dictionaries with things in them and I just need to be able to compare them to see if they contain the same objects. The compare function is defined on the base class, so what I'll do based on your advice is simply use Parent[] t = childObjects.Values.ToArray();I can loop through the array or convert that back to a dictionary. Not pretty but good enough for this.Thanks!
Frans