C#有办法给我一个不可变的字典吗?

ser*_*g10 68 .net c# java collections dictionary

核心C#库中是否有任何可以为我提供不可变字典的东西?

Java的一些东西:

Collections.unmodifiableMap(myMap);
Run Code Online (Sandbox Code Playgroud)

而且只是为了澄清,我不打算阻止键/值本身被改变,只是字典的结构.如果任何IDictionary的mutator方法被调用(Add, Remove, Clear),我想要快速和大声失败的东西.

dbk*_*bkk 52

不,但包装器相当简单:

public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
    IDictionary<TKey, TValue> _dict;

    public ReadOnlyDictionary(IDictionary<TKey, TValue> backingDict)
    {
        _dict = backingDict;
    }

    public void Add(TKey key, TValue value)
    {
        throw new InvalidOperationException();
    }

    public bool ContainsKey(TKey key)
    {
        return _dict.ContainsKey(key);
    }

    public ICollection<TKey> Keys
    {
        get { return _dict.Keys; }
    }

    public bool Remove(TKey key)
    {
        throw new InvalidOperationException();
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        return _dict.TryGetValue(key, out value);
    }

    public ICollection<TValue> Values
    {
        get { return _dict.Values; }
    }

    public TValue this[TKey key]
    {
        get { return _dict[key]; }
        set { throw new InvalidOperationException(); }
    }

    public void Add(KeyValuePair<TKey, TValue> item)
    {
        throw new InvalidOperationException();
    }

    public void Clear()
    {
        throw new InvalidOperationException();
    }

    public bool Contains(KeyValuePair<TKey, TValue> item)
    {
        return _dict.Contains(item);
    }

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
    {
        _dict.CopyTo(array, arrayIndex);
    }

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

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(KeyValuePair<TKey, TValue> item)
    {
        throw new InvalidOperationException();
    }

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
    {
        return _dict.GetEnumerator();
    }

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

显然,如果要允许修改值,可以更改上面的[] setter.

  • @Everyone else:如果你像我一样想知道,似乎有些人在"只读"和"不可变"之间有所区别."不可变"字典可以有一个Add方法,*返回*一个新的字典,其中添加了一个元素,而一个"只读"的字典没有,并且是获取"read-"的有用实例的唯一方法只有"字典是构建一个普通的字典,然后为它构造一个"只读"包装器. (13认同)
  • 这张海报很明显,当海报清楚地表示"只读"而不是"永恒".我认为这个包装可能符合他的需求,因此得分很高.我很高兴有人出来并获得了更多理论,但让我们不要忽视OP实际需要的东西. (6认同)
  • @Stefan:我认为它的区别不在于是否有任何方法可以从现有的集合中构建新的集合.像这个答案中的那个集合有一个只读接口:任何传递此实例的人都无法修改它,但不保证*没有人*可以修改它.(拥有原始`backingDict`的人可以修改集合.)另一方面,不可变的集合保证不被任何人修改. (4认同)
  • 您没有实现相等性检查,这是不可变数据结构的一个非常重要的特性. (3认同)
  • 看起来你所做的只是采用一个标准的词典,并在所有地方抛出异常......?"不变"并不一定意味着"无用".恰恰相反. (2认同)
  • 很有趣的是,当这个答案没有比C#自己的ReadOnlyCollection更多或不少的时候,这个答案是多么尖锐的人,除了它支持IDictionary <TKey,TValue>而不是IList <T>. (2认同)

Dyl*_*dor 14

随着.NET 4.5的发布,有一个新的ReadOnlyDictionary类.您只需将IDictionary构造函数传递给构造函数即可创建不可变字典.

是一个有用的扩展方法,可用于简化创建只读字典.