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
.
source share
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;
source share
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"];
source share
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);
source share