【问题标题】:ReadOnlyDictionary<TKey, TValue> with a ReadOnlyCollection<T>带有 ReadOnlyCollection<T> 的 ReadOnlyDictionary<TKey, TValue>
【发布时间】:2021-02-02 01:36:42
【问题描述】:

我有一堆类需要将属性返回为ReadOnlyCollection&lt;T&gt;s,当它们只是List&lt;T&gt;s 时效果很好,但是,与Dictionary&lt;TKey, TValue&gt; 中的列表相比,事情变得非常草率。

================================================ =

例如,这是一个典型的列表,我以 ReadOnlyCollection 的形式返回:

    private readonly List<string> _encryptionKeys;
    public ReadOnlyCollection<string> EncryptionKeys => _encryptionKeys.AsReadOnly();

================================================ =

但是,这是我需要为 ReadOnlyDictionary 做的转换:

    private readonly ReadOnlyDictionary<string, ReadOnlyCollection<string>> _attributes;
    public ReadOnlyDictionary<string, ReadOnlyCollection<string>> Attributes => _attributes;

...使用临时变量:

        Dictionary<string, List<string>> attributes = new Dictionary<string, List<string>>();

...向其中添加值及其列表,然后构建我的属性:

        Dictionary<string, ReadOnlyCollection<string>> readonlyListDictionary = new Dictionary<string, ReadOnlyCollection<string>>();
        foreach (string key in attributes.Keys)
            readonlyListDictionary.Add(key, attributes[key].AsReadOnly());
        _attributes = new ReadOnlyDictionary<string, ReadOnlyCollection<string>>(readonlyListDictionary);

================================================ =

有人有什么建议吗?

【问题讨论】:

  • 我建议避免使用ReadOnlyCollection&lt;T&gt;,原因有很多,我不会讨论。考虑改为返回IReadOnly... 接口。另请查看System.Collections.Immutable(因为与简单的IReadOnly... 相比,不变性为消费者提供了更大的保证)。
  • 您需要随机访问列表中的值吗?您可以改为从字典中创建一个查找,它实际上是一个只读的枚举字典。

标签: c# .net .net-5 c#-8.0


【解决方案1】:

把它变成一个扩展方法,那你就不用一直想它了:

public static ReadOnlyDictionary<TKey, ReadOnlyCollection<TValue>> AsReadOnly<TKey, TValue>(this Dictionary<TKey, List<TValue>> source)
{
    return new ReadOnlyDictionary<TKey, ReadOnlyCollection<TValue>>(
        new Dictionary<TKey, ReadOnlyCollection<TValue>>(
        source.Select(kvp =>
            new KeyValuePair<TKey, ReadOnlyCollection<TValue>>(kvp.Key, kvp.Value.AsReadOnly())
    ));
}

虽然,采用 IEnumerable&lt;KeyValuePair&gt; 的构造函数仅在 .NET 5 中可用。所以在早期版本中,我们必须使用 foreach。当我们预先调整字典大小时,这个选项也可能会更高效

public static ReadOnlyDictionary<TKey, ReadOnlyCollection<TValue>> AsReadOnly<TKey, TValue>(this Dictionary<TKey, List<TValue>> source)
{
    var dict = new Dictionary<TKey, ReadOnlyCollection<TValue>>(source.Count);
    foreach (var kvp in source)
        dict[kvp.Key] = kvp.Value.AsReadOnly();
    return new ReadOnlyDictionary<TKey, ReadOnlyCollection<TValue>>(dict);
}

就像使用其他 AsReadOnly 扩展程序一样使用它。

【讨论】:

  • 太美了!谢谢
【解决方案2】:

Linq 可以为您完成繁重的工作。

Dictionary<string, List<string>> input = new Dictionary<string, List<string>>();
ReadOnlyDictionary<string, ReadOnlyCollection<string>> output = new ReadOnlyDictionary<string, ReadOnlyCollection<string>>(dict.ToDictionary(kv => kv.Key, kv => kv.Value.AsReadOnly()));

【讨论】:

    猜你喜欢
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2011-01-16
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多