【问题标题】:Generic property in a non-generic class?非泛型类中的泛型属性?
【发布时间】:2011-10-08 00:18:34
【问题描述】:

我不知道该怎么做...

我有一个执行各种功能的类:

public abstract class EntityBase { ... }

public interface ISomeInterface<T> where T : EntityBase, new() { ... }

public class SomeClass<T> : ISomeInterface<T> { ... }

我正在尝试在非泛型类中缓存这些:

public class MyClass
{
    //Not sure how to do this
    private ConcurrentDictionary<?, ISomeInterface<?>> Cache { get; set; }
}

问题是 EntityBase 是抽象的,不能做 new(),ISomeInterface 需要一个基于 EntityBase 的类并做 new()。有什么办法可以做我想做的事吗?


更新:我意识到我可以为 TKey 使用 Type,但我仍然不确定 ISomeInterface 应该放什么。

【问题讨论】:

    标签: c# generics collections dictionary constraints


    【解决方案1】:

    首先,我认为您的意思是使用 ConcurrentDictionary,因为您有一个键/值对。

    其次,你可以像 ICloneable 那样做。 ICloneable 有一个返回 Object 而不是 T 的方法。

    private ConcurrentDictionary<Type, Object> Cache { get; set; }
    

    由于它是私有的,因此您可以在内部对其进行管理并根据需要进行投射。显然,您必须确保任何函数调用都有 typeparam 定义,例如:

    //I omitted error checking on all the examples.
    public class Foo : EntityBase { ... }
    
    void DoSomething<Foo>()
    {
        var someClass = Cache[typeof(Foo)] as ISomeInterface<Foo>
        someClass.Bar();
    }
    

    此外,即使该属性有另一个修饰符(public、internal、protected),您也可以将 cmets 添加到调用者,即 Object 是 ISomeInterface 的泛型类型,其中 T 是 EntityBase,new()。然后,他们只需要根据需要进行投射即可。


    您还可以在非泛型类上使用泛型方法来获取缓存项作为泛型类型:

    ISomeInterface<T> GetInstance<T>()
        where T : EntityBase, new()
    {
        return Cache[typeof(T)] as ISomeInterface<T>;
    }
    
    void AddInstance<T>(ISomeInterface<T> instance)
        where T : EntityBase, new()
    {
        Cache[typeof(T)] = instance;
    }
    
    void DoSomething<T>()
    {
        var someClass = GetInstance<T>();
        someClass.Bar();
    }
    

    【讨论】:

      【解决方案2】:

      查看这个相关问题:Making a generic property

      如果你不希望 MyClass 是泛型的,你可以使用两个泛型方法来代替:

          private ConcurrentCollection<T, ISomeInterface<T>> GetCache<T>()
          {
              ...
          }
      
          private void SetCache<T>(ConcurrentCollection<T, ISomeInterface<T>> cache)
          {
              ...
          }
      

      【讨论】:

      • 你将如何实现这些方法?
      • 我想我没有在我的回答中解决后备存储问题。 :)
      【解决方案3】:

      我不确定您到底想将该集合用于什么目的,但做类似事情的一种方法是创建一个包含值的嵌套通用静态类:

      class SomeInterfaceCollection
      {
          private static class Item<T>
          {
              public static ISomeInterface<T> Value;
          }
      
          public static ISomeInterface<T> Get<T>()
          {
              return Item<T>.Value;
          }
      
          public static void Set<T>(ISomeInterface<T> value)
          {
              Item<T>.Value = value;
          }
      }
      

      【讨论】:

      • 这只对静态属性有意义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多