Reputation: 21989
If we have field List<Dictionary<>>
, how to expose it as a readonly property?
To 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 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 readonly
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: it's a new list of new dictionaries.
What I would like to have is something similar to List<>.AsReadOnly(), to have property act as a wrapper over _list
.
Upvotes: 3
Views: 1859
Reputation: 12196
I've created a List of ReadOnlyDictionary
and populate it with the converted dictionaries, When i'm finished i'm converting the whole list into 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 similar to this with the methods you want to expose:
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 an 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 them your 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"];
Upvotes: 3
Reputation: 21989
There is no way to avoid creating new list, because Dictionary
items has to be converted to IReadOnlyDicionary
(by using Cast
or Select
). So here comes the question
Why it should be a list?
ReadOnlyList
is only used to access items by using index or in foreach
. So, why not simply provide that?
@Bas solution with indexer and simple property with yield return
produces 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; }
}
}
Dictionary (and list) is accessible as readonly from outside like this:
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);
Upvotes: 0
Reputation: 27085
If you cannot create a new list of Dictionary
objects, I would suggest to expose the items that you need from your class directly:
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;
Upvotes: 3