2

I have some code that fills two dictionaries

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

which I want to execute only when I need access to either of the dictionaries. As there are many methods that rely on the dictionaries being loaded I do not want to pollute all of them by calls to Load, like this:

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

Alternativly I could call the method within my constructor. However this implies Load is called in any case, regardless if any of the two dctionaries is ever used. That´s why I looked about Lazy. But as I have one method that should fill two parameters, I´m unsure on how to get this work.

So what I want to achieve is something like this:

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

2 Answers2

2

You can use 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

}

Or introduce class/struct to contain your dictionaries.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
1

You could either create your own struct to contain the two dictionaries, or just use a tuple for both of them.

Then you can use Lazy to initialise both of them like so:

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;
}

It is a bit more readable if you define a nested struct to hold your dictionaries:

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;
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276