Получатель для словарных элементов в C # 4.0 - PullRequest
3 голосов
/ 23 января 2012

Я хочу реализовать словарь, который создает свои собственные элементы на лету только тогда, когда к ним обращаются (не заранее). Для этого я хотел бы использовать метод getter, но я просто не нахожу никакой информации о том, как объявить getter в контексте элементов словаря.

Я понимаю, как добавить метод получения ко всему словарю (который должен возвращать словарь при вызове), но я хочу реализовать метод получения, который вызывается при обращении к одному элементу в словаре, чтобы я мог создать этот элемент на лету. Этот получатель должен получить ключ, который используется для запроса в качестве параметра, и он должен вернуть соответствующее значение.

Я не нахожу никакого синтаксиса для этой задачи в документации.

Ответы [ 3 ]

5 голосов
/ 23 января 2012

Вам просто нужно переопределить индексатор на 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();
}
0 голосов
/ 25 января 2012

Несмотря на то, что ответ Кева совершенно правильный и дан на профессиональном уровне, он все еще доставлял мне трудности (и положил начало многим плодотворным занятиям - спасибо Кев!)Как вы можете сказать, я изучаю C #, и есть много концепций, которые мне еще предстоит усвоить.Я хочу добавить ответ на свой вопрос здесь на тот случай, если у кого-то еще возникнет та же проблема, и он будет на том же уровне понимания, что и я.Возможно, это сэкономит немного времени.

Кев использовал Generics в своем ответе - отличная концепция, представленная в C # 2.Чтобы упростить ответ, я хочу показать его без обобщения и с большим количеством добавленных комментариев, которые дают подсказки ко всем концепциям, которые мне пришлось искать (и которые частично было непросто найти):

0 голосов
/ 23 января 2012

Это уже реализовано в фреймворке. Если вы позвоните

Dictionary<int, string> _myDictionary = new Dictionary<int, string>();

_myDictionary[1] = "Hello";
_myDictionary[2] = "World!";

ваш словарь будет заполнен парами ключ-значение <1, "Hello">, <2, "World!">

...