3

如果我们有 field List<Dictionary<>>,如何将其公开为只读属性?

例如:

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

我可以这样暴露

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

但仍然可以更改目录:

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

这是将其设为只读的尝试

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

我认为这种方法的问题是显而易见的:它是一个新字典的新列表。

我想要的是类似于List<>.AsReadOnly()的东西,让属性充当_list.

4

3 回答 3

3

如果你不能创建一个新的Dictionary对象列表,我建议直接从你的类中公开你需要的项目:

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

然后像这样使用它:

var test = new Test();

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

int count = test.ListCount;
于 2015-07-06T16:19:02.437 回答
3

我创建了一个列表ReadOnlyDictionary并用转换后的字典填充它,完成后我将整个列表转换为AsReadOnly.

代码:

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

旧解决方案:

您可以使用要公开的方法创建与此类似的包装器:

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
}

还有一个扩展方法:

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

他们的代码看起来像这样:

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

var roDict = dict.ToReadOnlyDictionary();
var a = roDict["2"];
于 2015-07-06T16:22:33.710 回答
0

无法避免创建新列表,因为Dictionary必须将项目转换为IReadOnlyDicionary(通过使用Castor Select)。那么问题来了

为什么它应该是一个列表?

ReadOnlyList仅用于通过使用 index 或 in 访问项目foreach。那么,为什么不简单地提供呢?

带有索引器和简单属性的@Bas 解决方案yield return生成最终解决方案:

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

字典(和列表)可以从外部以只读方式访问,如下所示:

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);
于 2015-07-07T08:32:15.487 回答