лениво загружать словарь - PullRequest
2 голосов
/ 17 июня 2020

У меня есть код, который заполняет два словаря

void Load(out Dictionary<string, string> m1, out Dictionary<string, string> m2) { ... }

, который я хочу выполнить, только когда мне нужен доступ к любому из словарей. Поскольку существует много методов, которые полагаются на загружаемые словари, я не хочу загрязнять их все вызовами Load, например:

void DoSomething()
{
    if(notYetInitialized) 
        Load(out this.dict1, out this.dict2);
    // do something with either dict1 or dict2
}

В качестве альтернативы я мог бы вызвать метод в моем конструкторе. Однако это подразумевает, что Load вызывается в любом случае, независимо от того, использовался ли когда-либо какой-либо из двух словарей. Вот почему я посмотрел около Lazy. Но поскольку у меня есть один метод, который должен заполнить два параметров, я не уверен, как получить эту работу.

Так что я хочу чего-то вроде это:

void DoSomething()
{
    var value = this.dict1[key]; // if dict1 is not yet loaded, call Load, which will also load dict2
}

Ответы [ 2 ]

2 голосов
/ 17 июня 2020

Вы можете использовать Lazy<(Dictionary<string, string> m1, Dictionary<string, string> m2)>:

private Lazy<(Dictionary<string, string> m1, Dictionary<string, string> m2)> _lazy;
private Dictionary<string, string> _dict1 => _lazy.Value.m1;    
private Dictionary<string, string> _dict2 => _lazy.Value.m2;
public SomeCtor()
{
    _lazy = new Lazy<(Dictionary<string, string> m1, Dictionary<string, string> m2)>(
          () => (new Dictionary<string, string>(), new Dictionary<string, string>())); // your actual logic to load dictionaries

}

Или ввести класс / структуру для хранения ваших словарей.

1 голос
/ 17 июня 2020

Вы можете либо создать свою собственную структуру, содержащую два словаря, либо просто использовать кортеж для них обоих.

Затем вы можете использовать Lazy для инициализации их обоих следующим образом:

public sealed class Test
{
    public Test()
    {
        _dicts = new Lazy<(Dictionary<string, string> m1, Dictionary<string, string> m2)>(initDicts);
    }

    public void DoSomething()
    {
        _dicts.Value.m1.Add("key", "value");
        _dicts.Value.m2.Add("key", "value");
    }

    (Dictionary<string, string> m1, Dictionary<string, string> m2) initDicts()
    {
        return (new Dictionary<string, string>(), new Dictionary<string, string>());
    }

    readonly Lazy<(Dictionary<string, string> m1, Dictionary<string, string> m2)> _dicts;
}

Это будет немного более читаемым, если вы определите вложенную структуру для хранения ваших словарей:

public sealed class Test
{
    public Test()
    {
        _dicts = new Lazy<Dicts>(initDicts);
    }

    public void DoSomething()
    {
        _dicts.Value.M1.Add("key", "value");
        _dicts.Value.M2.Add("key", "value");
    }

    Dicts initDicts()
    {
        return new Dicts(
            new Dictionary<string, string>(),
            new Dictionary<string, string>());
    }

    readonly struct Dicts
    {
        public Dicts(Dictionary<string, string> m1, Dictionary<string, string> m2)
        {
            M1 = m1;
            M2 = m2;
        }

        public readonly Dictionary<string, string> M1;
        public readonly Dictionary<string, string> M2;
    }

    readonly Lazy<Dicts> _dicts;
}
...