如何解决IReadOnlyDictionary缺乏协方差?

Oce*_*t20 22 .net c# dictionary readonly covariance

我正在尝试公开一个只读字典,该字典保存带有只读接口的对象.在内部,字典是可写的,其中的对象也是可写的(参见下面的示例代码).我的问题是,由于此处问题中概述的原因,IReadOnlyDictionary不支持协变转换.这意味着我不能只将我的内部字典公开为只读字典.

所以我的问题是,有没有一种有效的方法将我的内部字典转换为IReadOnlyDictionary,或者其他一些方法来处理它?我能想到的选择是:

  1. 保留两个内部词典并使它们保持同步.
  2. 访问属性并在其中转换所有对象时创建新字典.
  3. 在内部使用时,将IReadOnly转回NotReadOnly.

1看起来像是一种痛苦,2似乎非常低效.3听起来像目前最有希望,但仍然是丑陋的.我还有其他选择吗?

public class ExposesReadOnly
{
    private Dictionary<int, NotReadOnly> InternalDict { get; set; }
    public IReadOnlyDictionary<int, IReadOnly> PublicList
    {
        get
        {
            // This doesn't work...
            return this.InternalDict;
        }
    }

    // This class can be modified internally, but I don't want
    // to expose this functionality.
    private class NotReadOnly : IReadOnly
    {
        public string Name { get; set; }
    }
}

public interface IReadOnly
{
    string Name { get; }
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*Joe 16

您可以为字典编写自己的只读包装器,例如:

public class ReadOnlyDictionaryWrapper<TKey, TValue, TReadOnlyValue> : IReadOnlyDictionary<TKey, TReadOnlyValue> where TValue : TReadOnlyValue
{
    private IDictionary<TKey, TValue> _dictionary;

    public ReadOnlyDictionaryWrapper(IDictionary<TKey, TValue> dictionary)
    {
        if (dictionary == null) throw new ArgumentNullException("dictionary");
        _dictionary = dictionary;
    }
    public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); }

    public IEnumerable<TKey> Keys { get { return _dictionary.Keys; } }

    public bool TryGetValue(TKey key, out TReadOnlyValue value)
    {
        TValue v;
        var result = _dictionary.TryGetValue(key, out v);
        value = v;
        return result;
    }

    public IEnumerable<TReadOnlyValue> Values { get { return _dictionary.Values.Cast<TReadOnlyValue>(); } }

    public TReadOnlyValue this[TKey key] { get { return _dictionary[key]; } }

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

    public IEnumerator<KeyValuePair<TKey, TReadOnlyValue>> GetEnumerator()
    {
        return _dictionary
                    .Select(x => new KeyValuePair<TKey, TReadOnlyValue>(x.Key, x.Value))
                    .GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @vidstige可以通过在构造函数中从传入的字典中创建新字典来轻松解决. (3认同)
  • +1是因为您的课程在创建时不会读取整个源词典。这意味着即使对于庞大的词典来说,它也将很快。 (2认同)