当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《C#有办法给我一个不可变的字典吗?》经验,为你挑选了3个好方法。

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

Java的一些东西:

Collections.unmodifiableMap(myMap);

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



1> dbkk..:

不,但包装器相当简单:

public class ReadOnlyDictionary : IDictionary
{
    IDictionary _dict;

    public ReadOnlyDictionary(IDictionary backingDict)
    {
        _dict = backingDict;
    }

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

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

    public ICollection 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 Values
    {
        get { return _dict.Values; }
    }

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

    public void Add(KeyValuePair item)
    {
        throw new InvalidOperationException();
    }

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

    public bool Contains(KeyValuePair item)
    {
        return _dict.Contains(item);
    }

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

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

    public bool IsReadOnly
    {
        get { return true; }
    }

    public bool Remove(KeyValuePair item)
    {
        throw new InvalidOperationException();
    }

    public IEnumerator> GetEnumerator()
    {
        return _dict.GetEnumerator();
    }

    System.Collections.IEnumerator 
           System.Collections.IEnumerable.GetEnumerator()
    {
        return ((System.Collections.IEnumerable)_dict).GetEnumerator();
    }
}

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


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

2> Serhat Ozgel..:

据我所知,没有.但也许你可以从这些文章中复制一些代码(并学习很多):

C#中的不变性第一部分:C#中的不变性不可
变性第二部分:C#中一个简单的不可变堆栈
不变性:C#中协变不可变栈的
不变性第四部分:C#中一个不可变的队列
不变性:一个简单的二叉树
不可变性C#第七部分:关于二元树的更多信息
C#中的不变性第八部分:关于二元树的更多信息
C#中的不变性第九部分:学术界?加上我的AVL树实现
C#中的不可变性第10部分:一个双端队列
C#中的不可变性第十一部分:一个工作的双端队列


其中大部分现在都是来自微软的官方图书馆,可通过nuget获取 - [Immutable Collections](http://msdn.microsoft.com/en-us/library/dn467181.aspx)

3> Dylan Meador..:

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

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

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有