C#4.0中字典元素的getter

本文关键字:getter 元素 字典 C#4 | 更新日期: 2023-09-27 18:21:13

我想实现一个字典,它只在访问元素时(而不是事先)动态创建自己的元素。为此,我想使用getter方法,但我根本找不到任何关于如何在dictionary元素的上下文中声明getter的信息。

我确实理解如何将getter添加到整个字典中(调用时必须返回字典),但我想实现的是在访问字典中的单个元素时调用的getter,这样我就可以动态创建该元素。该getter必须接收用于请求的密钥作为参数,并且必须返回相应的值。

我在文档中找不到该任务的任何语法。

C#4.0中字典元素的getter

您只需要在Dictionary<,> 上重新实现索引器

    public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (!TryGetValue(key, out value))
            {
                value = Activator.CreateInstance<TValue>();
                Add(key, value);
            }
            return value;
        }
        set { base[key] = value; }
    } 
}

如果你需要一个更复杂的价值实例化,你可以使用激活器函数

 public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    readonly Func<TKey, TValue> _activator;
    public MyDictionary(Func<TKey, TValue> activator)
    {
        _activator = activator;
    }
    public new TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (!TryGetValue(key, out value))
            {
                value = _activator(key);
                Add(key, value);
            }
            return value;
        }
        set { base[key] = value; }
    } 
}

用法:

static void Main(string[] args)
{
    var dict = new MyDictionary<int, string>(x => string.Format("Automatically created Value for key {0}", x));
    dict[1] = "Value for key 1";
    for (int i = 0; i < 3; i++)
    {
        Console.WriteLine(dict[i]);
    }
    Console.Read();
}

虽然Kev的答案完全正确,而且是专业水平的,但它仍然给了我一段艰难的时间(并启动了许多富有成效的学习-谢谢Kev!)。正如你所知,我是一个学习C#的人,还有很多概念我还需要吸收。我想在这里为我自己的问题添加一个答案,以防其他人也有同样的问题,并且与我的理解水平相似。也许这会节省一些直播时间。

Kev在他的回答中使用了泛型——这是一个用C#引入的伟大概念。为了简化答案,我想在没有泛型的情况下展示它,并添加了很多注释,这些注释暗示了我必须查找的所有概念(部分不容易找到):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DictionaryElementsGetter_Test {
  // class inherits from Dictionary<int, string>
  public class MyDictionary : Dictionary<int, string> {
    // new: hide element of base class to redefine it in derived class.
    //      see http://msdn.microsoft.com/en-us/library/435f1dw2.aspx
    // string this[int key]: create an indexer
    //                       (actually: replace the indexer of base class, because of "new")
    //                       see http://msdn.microsoft.com/en-us/library/2549tw02.aspx
    new public string this[int key] {
      get {
        string value;
        // out: pass argument by reference instead of by value
        //      This is the standard definition of TryGetValue.
        //      Beside the bool result that indicates the existence of the key-value-pair,
        //      TryGetValue also returns the value itself into this reference parameter (if key is found).
        //      see http://msdn.microsoft.com/en-us/library/ee332485.aspx
        if( !TryGetValue( key, out value ) ) {
          value = "abc" + key + "def";
          Add( key, value );
          // just to see when the getter really did an Add():
          Console.Write( "ADDED!... " );
        }
        return value;
      }
      // base: access element of the base class Dictionary<int, string>
      //       see http://msdn.microsoft.com/en-us/library/hfw7t1ce(v=vs.100).aspx
      set { base[key] = value; }
    }
  }

  class Program {
    static void Main( string[] args ) {
      var dict = new MyDictionary();
      dict[1] = "EXTERNAL VALUE";
      for( int i = 0; i < 3; i++ ) {
        Console.WriteLine( i + ": " + dict[i] );
      }
      /* 
      Output:
        ADDED!... 0: abc0def
        1: EXTERNAL VALUE
        ADDED!... 2: abc2def
      */
      for( int i = 0; i < 3; i++ ) {
        Console.WriteLine( i + ": " + dict[i] );
      }
      /* 
      Output:
        0: abc0def
        1: EXTERNAL VALUE
        2: abc2def
      */
      Console.ReadKey();
    }
  }
}

它已经在框架中实现了。如果你打电话给

Dictionary<int, string> _myDictionary = new Dictionary<int, string>();
_myDictionary[1] = "Hello";
_myDictionary[2] = "World!";

您将使您的字典填充有键值对<1、"你好">,<2,"世界!">