【问题标题】:Return HashSet<T> from HashSet of generic type in generic function在泛型函数中从泛型类型的 HashSet 返回 HashSet<T>
【发布时间】:2017-03-19 13:41:58
【问题描述】:

我有一个 Dictionary&lt;Type, HashSet&lt;GenericType&gt;&gt; 用于保存我的数据,我正在尝试创建一个函数,它返回给定泛型类型 T : GenericType 的这些 HashSet 之一。

基本上

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&lt;T&gt; 每次 Get 被调用,然后使用 foreach 循环转换并从已经存在的 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>();
    }
}

【问题讨论】:

  • 你需要返回一个协变接口。
  • 请澄清:您获得了Dictionary&lt;Type, HashSet&lt;GenericType&gt;&gt;,并且您已经可以从您的Dictionary 中检索特定的HashSet&lt;GenericType&gt;,但无法从上述HashSet 中检索GenericType。对吗?
  • 是的,我可以毫无问题地从字典中获取 HashSet。然后我有一个 HashSet,我不能将它作为 HashSet 返回
  • @Tokfrans 你能告诉我更多的代码吗?基本上,您如何定义声明 data 的类。只需从类中删除与问题无关的所有内容。因为仅仅指定类 class Klass&lt;TGenericType&gt; : IKlass&lt;out TGenericType&gt; { .. } 可能就足够了。
  • @SvenM。虽然我已经更新并试图解释我的情况,但我不确定你的意思。

标签: c# generics covariance contravariance


【解决方案1】:

我只想更改字典的类型,然后在您的 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 中对一个密切相关的问题进行了更多讨论。

【讨论】:

  • 是的,将字典设为私有将确保其中不会有任何其他内容 - 好主意!感谢您的帮助。
  • 我删除了我提出的解决方案,因为它完全没有达到目标,并且没有必要用该代码混淆人们。 Jon Skeet 的想法真是太聪明了。好吧,他是寻找更坚硬的坚果的最佳人选。 ;)
猜你喜欢
  • 1970-01-01
  • 2020-10-26
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多