Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary of generic lists or varying types

Tags:

I want to have a Dictionary that maps strings to generic lists of varying types. i.e. in the following form:

 Key        Value string     List<T> string     List<U> string     List<V> string     List<U> ... 

Currently I'm using a Dictionary<string, IList> and then extracted the strongly typed list from each dictionary KeyValuePair<string, IList> pair entry as follows:

Type layerType = pair.Value.GetType().GetGenericArguments()[0]; List<layerType> objectsClicked = pair.Value as List<layerType>; 

Is there a nicer way to do this?

[Edit] As has been noted, the above doesn't compile, apologies - that's what you get when you ask a question while you're still working on somethings. Some more explanation. I'm making a basic spatial data viewer. The final view consists of a group of Layer<T>s. Each layer provides a delegate to render its type (given an offset and scale) and a way to check which of its objects are in the current window. For hit testing, I would like a List for each Layer of which objects have been hit. That list would be a List<Point> for a Point layer, etc... The grouping of the hits from all the Layer<T>s would then be a collection of strongly typed lists.

like image 691
Matthew Finlay Avatar asked Feb 18 '11 05:02

Matthew Finlay


2 Answers

How about Dictionary<string, dynamic> assuming you're on C# 4

Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>(); Dict.Add("int", new List<int>()); Dict.Add("string", new List<string>());  Dict["int"].Add(12); Dict["string"].Add("str");  foreach (KeyValuePair<string, dynamic> pair in Dict) {    Type T = pair.Value.GetType();    Console.WriteLine(T.GetGenericArguments()[0].ToString()); } 

That prints out

System.Int32

System.String

Is that what you're looking for?

like image 181
Adam Rackis Avatar answered Nov 12 '22 05:11

Adam Rackis


I am going to take a middleground between Euphoric and Adam, you should make use of both IList and dynamic. This is what I think is more correct:

var dict = new Dictionary<string, IList>(); dict.Add("u", new List<U>()); dict.Add("v", new List<V>());  // in case of members you know they exist on an IList dict["u"].Add(new U()); dict["v"].Add(new V());  // in case you know what you are going to get back, in which case you should cast var uProperty = (dict["u"][0] as U).UProperty var vProperty = (dict["v"][0] as V).VProperty  // in case your're not sure of      (dict[someKey] as dynamic)[someIndex].SomeMember...; 

All these are much simpler than relying on reflection. The basic idea is declare the dictionary value type as IList to make your intentions clearer up front, while make use of dynamic to ease the reflection monstrosity and make code shorter.

like image 37
nawfal Avatar answered Nov 12 '22 04:11

nawfal