Readonly List <Dictionary <>>

If we have a field List<Dictionary<>>

, how do we expose it as a readonly property?

Example:

public class Test
{
    private List<Dictionary<string, object>> _list;
}

      

I can expose it like this:

public ReadOnlyCollection<Dictionary<string, object>> List
{
    get { return _list.AsReadOnly(); }
}

      

but it is still possible to change the directory:

var test = new Test();
test.List[0]["a"] = 3; // possible
test.List[0].Add("e", 33); // possible

      

Here is an attempt to make it read-only

public ReadOnlyCollection<ReadOnlyDictionary<string, object>> List
{
    get
    {
        return _list.Select(item =>
            new ReadOnlyDictionary<string, object>(item)).ToList().AsReadOnly();
    }
}

      

I think the problem with this approach is obvious: this is a new list of new dictionaries.

I would like to have something similar to List <>. AsReadOnly () so that the property is executed as a wrapper over the _list

.

+3


source share


3 answers


If you are unable to create a new list of objects Dictionary

, I would suggest to directly view the elements you need from your class:

public IReadOnlyDictionary<string, object> this[int i] 
{
    get { return this._list[i]; }
}
//OR
public IReadOnlyDictionary<string, object> GetListItem(int i)
{
    return _list[i];
}

public int ListCount
{
    get { return this._list.Count; }
}  

      



Then use it like this:

var test = new Test();

var dictionary = test[0];
//OR
dictionary = test.GetListItem(0);

int count = test.ListCount;

      

+3


source


I created a list ReadOnlyDictionary

and filled it with converted dictionaries. When I'm done, I iterate over the entire list in AsReadOnly

.

Code:

public ReadOnlyCollection<ReadOnlyDictionary<string, object>> AsReadOnlyListAndElements
{
    get
    {
        var list = _list.Select(elem => new ReadOnlyDictionary<string, object>(elem));
        return list.ToList().AsReadOnly();
    }
}

      

Old solution:

You can create a wrapper like this with the methods you want to open:



public class ReadOnlyDict<K, V>
{
    private Dictionary<K, V> dictionary;

    public ReadOnlyDict(Dictionary<K, V> dict)
    {
        dictionary = dict;
    }

    public V this[K key]
    {
        get
        {
            return dictionary[key];
        }
    }

    // Add more methods per your request
}

      

And the extension method:

namespace System.Collections.Generic
{
    public static class DictionaryExt
    {
        public static ReadOnlyDict<K, V> ToReadOnlyDictionary<K, V>(this Dictionary<K, V> dict)
        {
            return new ReadOnlyDict<K, V>(dict);
        }
    }
}

      

And their code will look something like this:

Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("2", "2");
dict.Add("3", "3");

var roDict = dict.ToReadOnlyDictionary();
var a = roDict["2"];

      

+3


source


There is no way to avoid creating a new list, because the Dictionary

elements must be converted to IReadOnlyDicionary

(with Cast

or Select

). So the question arises

Why should it be a list?

ReadOnlyList

only used to access items by index or in foreach

. So why not just provide this?

@ Bas's solution with index and simple property with yield return

gives the final solution:

public class Test
{
    private List<Dictionary<string, object>> _list = new List<Dictionary<string, object>>();

    public IEnumerable<IReadOnlyDictionary<string, object>> Items
    {
        get
        {
            foreach (var item in _list)
                yield return item;
        }
    }

    public IReadOnlyDictionary<string, object> this[int i]
    {
        get { return _list[i]; }
    }

    public int Count
    {
        get { return _list.Count; }
    }
}

      

The dictionary (and the list) is available as originally from the outside:

var test = new Test();
Console.WriteLine(test[0]["a"]); // direct access
foreach (var item in test.Items) // enumeration
    foreach(var dic in item)
        Console.WriteLine(dic);

      

0


source







All Articles