Lazy dictionary properties in C#
Asked Answered
S

2

8

I have a class with a property that's a Dictionary:

public class Entity 
{
    public Dictionary<string, string> Name { get; set; }
}

I would like switch this property to use lazy initializtion. I tried the following:

public class Entity 
{
    private Lazy<Dictionary<string, string>> name = new Lazy<Dictionary<string, string>>(() => new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase));
    public Dictionary<string, string> Name
    {
        get => name;
        set => name = value;
    }
}

This is of course an error, as Name and name have different types. For the life of me though, I can't figure out how to specify this correctly. All I really want is to have Name remain null until I access it, then create it on the first read or write.

Soniferous answered 3/4, 2012 at 23:31 Comment(1)
[Realizing this question is 8 years old] Is "Using Lazy and ConcurrentDictionary to ensure a thread-safe, run-once, lazy-loaded collection" similar to what you were after?Swahili
H
12

You can use the initialization with Lazy, but what you want is pretty simple and you could simply do this

private Dictionary<string, string> _name;
public Dictionary<string, string> Name
{
    get
    {
        if (_name == null)
            _name = new Dictionary<string, string>();
        return _name;
    }
    set _name = value;
}

EDIT: Note that this approach will have some thread safety issues. Check if this can be a problem for you.

Haroldharolda answered 3/4, 2012 at 23:34 Comment(6)
You have a race condition in there.Subaqueous
Yeah added I added a note about this probably as you were typing your comment. ;)Haroldharolda
D'oh, looks like I was using my complicator's gloves. This is what happens when I become enamored with a cool feature. Thanks, I'll mark this as the answer as soon SO lets me. Now, because I have a bunch of these, I just need to make some sort of factory for them.Soniferous
or just get { return _name ?? (_name = new Dictionary<string, string>()); }Fiesole
Yeah that's a nice one liner but some people won't like to assign in the return. I guess you lose some readability.Haroldharolda
Or in C# early versions get => _name ??= new();Landsturm
A
10

name.Value is read-only. Try this:

public class Entity 
{
    private Lazy<Dictionary<string, string>> name = 
        new Lazy<Dictionary<string, string>>(
            () => new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase));
    
    public Dictionary<string, string> Name => name.Value;
}
Amusing answered 3/4, 2012 at 23:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.