【问题标题】:How to create a strongly typed collection that only contains one element per type如何创建每个类型只包含一个元素的强类型集合
【发布时间】:2014-01-21 07:47:35
【问题描述】:

我正在尝试创建一个集合,每个类型只包含一个元素。然而,每种类型都必须继承一个根类型,以便具有共性。 我做了一些研究,想知道我是否走在正确的轨道上,或者是否可以进行一些改进:

class TypedList<T> : Dictionary<Type, T> {

    public override void Add<C>(T instanceOfType) {
        base.Add(typeof(C), instanceOfType);
    }

}

具体问题:

  • 这是正确/最好的方法吗?
  • 我应该怎么做才能方便检索元素?
  • 如果 Add() 方法是正确的,有没有办法强制 C 是 T 的子类?

更新代码以反映 Ondrej 的建议:

class TypedList<Abstract> : IList<Abstract> {

    protected Dictionary<Type, Abstract> data;

    public void TypedList() {
        data = new Dictionary<Type, Abstract>();
    }

    public void Add<Concrete>(Concrete instanceOfType) where Concrete : Abstract {
        data.Add(typeof(Concrete), instanceOfType);
    }

} 

【问题讨论】:

  • 是否意味着每种类型都有一个单例?
  • 可以有多个 typedList 实例,其中包含同一类的不同实例。所以它不会是每个 VM 一个类一个,不。
  • 在更新版本中,您应该使用typeof(Concrete),而不是typeof(Abstract)。另请注意,以T 开头的类型参数是一种常见的约定。

标签: c# collections strong-typing


【解决方案1】:

这种方法通常看起来不错。但是,我会考虑将Dictionary&lt;Type, T&gt; 隐藏为私有字段并重新实现您想要的接口。不一定是IDictionary&lt;Type, T&gt;,也可以是IList&lt;T&gt;

另一种选择是使用List&lt;T&gt; 进行内部存储,使用HashSet&lt;Type&gt; 维护列表中的项目类型集。这样的底层存储可能更适合IList&lt;T&gt;TypedList&lt;T&gt; 的所需接口,解决字典“缺失索引”问题。

另外,Add&lt;C&gt; 方法声明似乎不正确。您应该将其声明为:

public override void Add<C>(C instanceOfType) where C : T {
    base.Add(typeof(C), instanceOfType);
}

这确保C 将成为T 的祖先。在您的原始声明中,C 可能是任何类型,可能与 T 无关。

【讨论】:

  • 对于将IDictionary 的其余方法映射到包装好的IList,您有什么建议吗?
  • 我会以最直接的方式实现IList&lt;T&gt;,尊重“single-value-per-type-key”约束所施加的唯一语义。实现应该是微不足道的。
  • 这可能是个问题。您可以模拟它(维护一个订单),使用哈希码(并忍受事实索引将是稀疏的),或使用另一个底层存储(请参阅更新的答案)。
  • 这真的取决于你的类接口的语义。这在您最初的问题中并不清楚,因此请将我的回答视为对各种可能性的建议。
  • 是的。或ICollection&lt;T&gt;...
【解决方案2】:

这应该给你你正在寻找的约束!

类 TypedList : 字典 {

public override void Add<C>(T instanceOfType) where C : T{
    base.Add(typeof(C), instanceOfType);
}

}

但是,我想知道您为什么不直接使用字典? IE。您子类化的字典应该按照您希望的方式运行?

【讨论】:

    【解决方案3】:

    几个月后,我想我想出了一个非常好的解决方案,那就是使用我最初不知道的集合KeyedCollection

    public class TypedSet<AbstractType> : KeyedCollection<Type, AbstractType> {
    
        protected override Type GetKeyForItem(AbstractType item) {
            return item.GetType();
        }
    
    }
    

    非常简洁,不需要将不同类型的集合类拼接在一起。使代码更加惯用,而且KeyedCollection 是抽象的,需要实现GetKeyForItem

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多