【问题标题】:Make Hashtable immutable使哈希表不可变
【发布时间】:2009-10-19 16:18:39
【问题描述】:

如何从 Hashtable 中创建派生类,其对象可以添加,但不能删除或替换?

我必须重写什么,特别是如何重写 [] 运算符?

【问题讨论】:

  • 您为什么要使用 Hashtable 而不是通用集合?
  • 唯一的原因是我对 C# 中的可用集合没有任何合理的了解,所以我只在需要字符串->对象索引器时使用 Hashtable。
  • 实际上,我在 Hashtable 中添加了两种不同的类型,这就是我不使用泛型集合的原因。
  • 您仍然应该使用泛型类。如果您希望获得与 HashTable 相同的键和值类型,您甚至可以使用 Dictionary,但通常您可以更具体地了解类型。

标签: c# hashtable overriding immutability


【解决方案1】:

在这种情况下,您可能应该封装它,而不是从 Dictionary(您应该使用它而不是 HashTable)派生。

Dictionary 有很多允许更改集合的方法,将其设置为私有成员更容易,然后只需实现添加和访问项目的方法。

类似:

public class StickyDictionary<Key, Value> : IEnumerable<KeyValuePair<Key, Value>>{

   private Dictionary<Key, Value> _colleciton;

   public StickyDictionary() {
      _collection = new Dictionary<Key, Value>();
   }

   public void Add(Key key, Value value) {
      _collection.Add(key, value);
   }

   public Value this[Key key] {
      get {
         return _collection[key];
      }
   }

   public IEnumerable<KeyValuePair<Key, Value>> GetEnumerator() {
      return _collection.GetEnumerator();
   }

}

【讨论】:

  • 对,你不应该派生一个类然后改变它的默认行为(而不是扩展它)。如果你这样做,Dictionary 的用户可能会通过 ImmutableDictionary 的一个版本,并惨遭失败,因为它的行为不像 Dictionary 所期望的那样。
  • 不,我的类不打算用作集合,而只是存储了许多可以通过几种不同方式访问的对象。
  • 那么封装集合而不是从它派生是很有意义的。
【解决方案2】:

您至少应该覆盖ClearRemove、属性Values 和索引器Item。您可以使用以下语法覆盖索引器Item

public override this[object key] {
    get { // get implementation }
    set { // set implementation }
}

您需要覆盖Clear,以便用户无法清除哈希表。您需要覆盖 Remove 以便用户无法从哈希表中删除全部内容。您需要覆盖Values,因为用户可以使用返回的ICollection 来修改哈希表中的值。出于类似的原因,您需要覆盖 Item

【讨论】:

  • 谢谢。我刚刚实现了 Add 和 indexer,并使用了组合而不是继承。
  • 请注意,这仅在派生自 HashTable 时有效。如果您从 Dictionary 派生,则至少还有另外三种方法需要遮蔽。
  • @HeavyWave:请注意,我回答了您的问题,但是其他人在解释为什么您不应该这样做方面做得非常出色。特别是,您违反了 Liskov 替换原则 (en.wikipedia.org/wiki/Liskov_substitution_principle)。 (例如,在Hashtable 上调用Clear 然后Count 将产生零值,但在派生类上调用Clear 然后Count 不会。)
猜你喜欢
  • 2020-06-07
  • 2021-09-05
  • 1970-01-01
  • 2018-04-04
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多