从泛型函数中的泛型类型的HashSet返回HashSet <t>

时间:2017-03-19 13:41:59

标签: c# generics covariance contravariance

我有一个Dictionary<Type, HashSet<GenericType>>用于保存我的数据,我正在尝试创建一个函数,在给定泛型类型T : GenericType的情况下返回其中一个HashSets。

基本上

Dictionary<Type, HashSet<GenericType>> data;

public HashSet<T> Get<T>() where T : GenericType
{
    var tp = typeof(T);
    //....check if its in the dictionary, fill if not....
    return data[tp];
}

当然这不是有效的。但我很难搞清楚应该做些什么。 我觉得回归T是最佳的,因为你可以这样做:

Get<Derived>().Where(x => x.DerivedProperty == someValue)

但我唯一想到的是每次调用 HashSet<T>时创建一个新的Get ,然后使用foreach-loop强制转换并添加每个项目字典中已经存在的HashSet,但这感觉真是浪费?

另一个想法是跳过HashSet并使用另一个(协变?)集合。但是,由于这些集合将包含批次数据,也许它不是最好的主意。

所以简而言之,我想知道这个问题的最佳方法是什么。

更新

所以这就是我得到的结构。包含data的类型是我的代码结构中的一种服务。它将通过反射在运行时加载和初始化。从那以后,我稍后使用各种ServiceFactory来获得该服务。

public class foo : Service
{
    public Dictionary<Type, HashSet<BaseClass>> data = new Dictionary<Type, HashSet<BaseClass>>();

    public T Get<T>() where T : BaseClass
    {
        var tp = typeof(T);

        if (!data.ContainsKey(tp))
        {
            data.Add(typeof(Derived), new HashSet<BaseClass>() { new Derived(), new Derived(), new Derived() });
        }

        return data[tp];//this wont compile.
    }
}

public class Derived : BaseClass
{
    public int ExampleVariable {get;set;}
}

public abstract class BaseClass
{
    // some things in here.
    public void DoCommonStuff()
    {

    }
}

class program
{

    static void Main(string[] args)
    {
        var service = ServiceFactory.GetService<foo>();
        var collection = service.Get<Derived>();
    }
}

1 个答案:

答案 0 :(得分:3)

我只想更改字典的类型,并在Get方法中强制转换。当然,绝对要让你的字典保密 - 那么你可以确保只有你的代码(理想情况下只有Get方法)可以访问它:

// Any data[typeof(Foo)] value will be a HashSet<Foo>. Only
// the Get method should access this dictionary.
private readonly Dictionary<Type, object> data = new Dictionary<Type, object>();

public HashSet<T> Get<T>() where T : GenericType
{
    var tp = typeof(T);
    object value;
    if (data.TryGetValue(tp, out value))
    {
        return (HashSet<T>) value;
    }

    var newSet = new HashSet<T>()
    // Populate newSet here
    data[tp] = newSet;
    return newSet;
}

我在blog post中对一个密切相关的问题进行了更多的讨论。