通用列表或不同类型的字典

时间:2011-02-18 05:37:08

标签: c#

我想要一个将字符串映射到不同类型的通用列表的Dictionary。即以下列形式:

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

目前我正在使用Dictionary<string, IList>,然后从每个字典KeyValuePair<string, IList> pair条目中提取强类型列表,如下所示:

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

有更好的方法吗?

[编辑] 正如已经指出的那样,上面的内容并没有编译,道歉 - 这就是当你在做某些事情的同时问一个问题时所得到的。 更多解释。我正在制作一个基本的空间数据查看器。最终视图由一组Layer<T>组成。每个图层都提供一个委托来呈现其类型(给定偏移量和比例)以及检查其对象在当前窗口中的方式。对于命中测试,我希望每个图层的列表都被击中了对象。对于List<Point>图层,该列表将是Point等等......来自所有Layer<T>的点击的分组将是强类型列表的集合。

4 个答案:

答案 0 :(得分:40)

Dictionary<string, dynamic>假设您使用的是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());
}

打印出来

  

System.Int32

     

System.String

这就是你要找的东西吗?

答案 1 :(得分:2)

使用Dictionary<string, IList>可能只是解决方案。但是你的代码是错的,你不能使用这样的泛型。你不能像这样创建动态类型。

您需要的一般问题是它与C#等强类型语言不兼容。在强类型语言中,您必须知道什么类型是完全类型。但是不能用正常手段来完成。你对泛型的理解也是错误的。它只是该类型的编译时扩展。

一般的想法:在您的情况下,使用您保存在这些列表中的某种类型的OOP层次结构。这将是一个更好,更安全的想法,并不会让每个看着你的代码的人撕掉他的头发。

答案 2 :(得分:2)

我将采取Euphoric和Adam之间的中间地带,你应该使用IListdynamic。这是我认为更正确的方法:

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...;

所有这些都比依靠反思简单得多。基本思想是将字典值类型声明为IList,以使您的意图更加清晰,同时利用dynamic来减轻反射怪物并缩短代码。

答案 3 :(得分:0)

我实际上认为更简洁的方法是为您的字典创建一个包装器:

public class GlobalStore
{
    private readonly IDictionary<Type, IEnumerable> _globalStore;

    public GlobalStore()
    {
        _globalStore = new ConcurrentDictionary<Type, IEnumerable>();
    }

    public IEnumerable<T> GetFromCache<T>()
        where T : class 
    {
        return (IEnumerable<T>) _globalStore[typeof(T)];
    }

    public void SetCache<T>(IEnumerable<T> cache)
        where T : class
    {
        _globalStore[typeof(T)] = cache;
    }
}

以下是对它的测试:

[TestClass]
public class GlobalStoreTest
{
    [TestMethod]
    public void GlobalStore_Test()
    {
        //Arrange
        var globalStore = new GlobalStore();
        globalStore.SetCache(new List<ClientModel>
        {
            new ClientModel
            {
                ClientId = 1,
                ClientName = "Client1"
            },
            new ClientModel
            {
                ClientId = 2,
                ClientName = "Client2"
            }
        });

        //Act
        var clients = globalStore.GetFromCache<ClientModel>();

        //Assert
        Assert.AreEqual(2, clients.Count());
    }
}