【问题标题】:Overloading the index operators in a Dictionary subclass重载 Dictionary 子类中的索引运算符
【发布时间】:2015-03-08 05:18:21
【问题描述】:

我有一段时间在服务出现时将一组数据重建到 .NET 字典中。最近那组数据变得如此之大,我决定我只想根据需要实际构建 kev/value 对象。所以我的想法是,从 Dictionary 继承,并重载索引运算符。在那里我将检查集合是否包含键(并返回值),如果不包含,我将创建对象将其填充到集合中并返回。

我尝试下面的代码(为简单起见,我只使用了字符串类型的值,而不是我实际创建的相当复杂的对象):

  public class BroadcastDictionary<TKey, TItem> : Dictionary<TKey, TItem>
  {
     public string this[TKey key]
     {
        get
        {
           if (!base.ContainsKey(key))
           {
              try
              {
                 //Construct the object and put it
                 // into the collection:
                 string newValue = "new value!";
                 base.Add((TKey)key, (TItem)newValue);
              }
              catch
              {
                 ;// Log the lazy object generation failure
              }
           }

           if (base.ContainsKey(key))
              return base[key].ToString();
           else
              throw new Exception("BroadcastDictionary value object lazy load failure.");
        }
     }
  }

但是,我因无法使用 Dictionary.Add(key, value) 插入值而感到困惑。关于如何修复这段代码并使其发挥作用的任何想法?

编辑:问题是上面的代码无法编译。在base.Add((TKey) key, (TItem)newValue); 处,编译器报告错误“错误 2 无法将类型 'string' 转换为 'TItem'”。

【问题讨论】:

  • 您最好从 IDict 派生并将 Dict 存储为字段。这样您就可以控制一切并且不会泄露实现细节。
  • 你真的需要通用的键和值吗?如果没有,您可以使用支持字典的索引器执行此操作。
  • “挂断无法插入”如何?它是否会抛出异常,说明该项目已经在字典中?如果是这样,你有多个线程打这个东西吗?在这种情况下,您可能需要在 try/catch 周围加一个锁,这样一次只能有一个线程到达那里。
  • Dictionary 继承时不能重载索引器。您只能隐藏它,这意味着任何拥有您的字典的人都可以将其转换为 Dictionary 并使用基类的索引器,从而颠覆您的所有代码。
  • 在实际实现中,您可以将 string newValue = "new value!"; 行替换为实际构造 TItem 而不是字符串的内容。

标签: c# .net inheritance dictionary data-structures


【解决方案1】:

为此,您作为 Add 的 value 参数传递的内容必须是 TItem。您的字典的值类型是 TItem,所以您可以添加到它的所有内容。 index 方法也应该使用 new 关键字。只要 TItem 有一个公共的无参数构造函数,下面的代码就可以懒惰地创建它:

public class BroadcastDictionary<TKey, TItem> : Dictionary<TKey, TItem> where TItem : new()
{
    public new string this[TKey key]
    {
        get
        {
            if (!base.ContainsKey(key))
            {
                try
                {
                    //Construct the object and put it
                    // into the collection:
                    var item = new TItem();
                    base.Add(key, item);
                }
                catch
                {
                    ;// Log the lazy object generation failure
                }
            }

            if (base.ContainsKey(key))
                return base[key].ToString();
            else
                throw new Exception("BroadcastDictionary value object lazy load failure.");
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-01
    • 2013-10-23
    • 2021-09-17
    • 2021-07-10
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多