views:

260

answers:

3

I've got an object which is a Dictionary of an unknown type (ie I don't know the type for the key and the value)

I want to retrieve all of its values so I can access those by index.

So what I want to do is something like that :

Dictionary<object, object> d = (Dictionary<object, object>)obj; // cast error
l = new List<KeyValuePair<object,object>>();
foreach (KeyValuePair<object, object> k in d)
   l.Add(new KeyValuePair<object,object>(k.Key, k.Value));

However, as expected, the runtime won't let me cast to a Dictionary< object, object>.

Is there a way to do this in .net 3.0 ? (for example using reflection?)

+13  A: 

Since Dictionary<,> implements IDictionary (non-generic), just iterate that:

    IDictionary data = ...
    foreach (DictionaryEntry de in data)
    {
        Console.WriteLine(de.Key + ": " + de.Value);
    }
Marc Gravell
I believe the issue is actually with casting an object to a Dictionary<,> as opposed to iterating its entries.
Tim S. Van Haren
@tsvanharen - This approach solves that problem.
codekaizen
A: 
Ed Woodcock
+4  A: 

You can't cast obj to a Dictionary<object, object> because it isn't a Dictionary<object, object>. Yes, its keys and values derive from object, and can be thus cast to object. But you can't cast generic types in C# because they aren't covariant. Even though T derives from object, List<T> doesn't derive from List<object>.

Consider this method:

void ModifyList<List<object> list)
{
   for (int i=0; i<list.Count; i++)
   {
      list[i] = list[i].ToString();
   }
}

If you could cast List<int> to List<object>, you could pass a List<int> to that method and it would turn into something else.

This is going to change when covariant generics are introduced in C# 4.0. This article is a pretty good explanation of the issues involved.

But to solve your actual problem, this will do the trick:

List<KeyValuePair<object, object>> list = d.AsEnumerable()
   .Select(x => new KeyValuePair<object, object>(x.Key, x.Value))
   .ToList();
Robert Rossney
For info; C# 4.0 covariance will make no difference to `List<T>` (nor `IList<T>`, nor any of the dictionary types); only simpler things like `IEnumerable<T>` and the `Func<...>` types; http://marcgravell.blogspot.com/2009/02/what-c-40-covariance-doesn-do.html
Marc Gravell
Right. Adding this feature to the language doesn't make casting collection classes a good idea, or even possible. List<T> is both covariant and contravariant; T is used in both an output position (e.g. the indexer returns an object of type T) and an input position (e.g. Add(T item)).
Robert Rossney