c#安全地返回字典引用



考虑到代码安全性和对代码可读性/视觉性的影响,我正在考虑三种方法来返回内部字典实例(c#)的引用。

我已经将其缩小到以下三种方法,但我愿意接受更好的建议。目前我更喜欢#3,因为在不增加锅炉板的情况下,安全平衡最好。

1)使用第二个ReadOnlyDictionary实例来包装内部Dictionary,只允许ReadOnlyDictionary转义类:

2)将Dictionary实例返回为IReadOnlyDictionary,但重铸将允许对其进行修改,因此不像选项#1或#3那样安全。

3)返回dictionary . toimmutabledictionary()作为ImmutableDictionary,当它转义包含的类,使返回的对象是内部字典的不可变视图时,尽管这会为每个调用生成一个新的副本,从而产生更高的成本,但对于小型简单字典(我的就是)来说,这应该是好的。

    private readonly Dictionary<string, string> innerDictionary = new Dictionary<string, string>();
    // Only required for Example #1
    private readonly IReadOnlyDictionary<string, string> readonlyInnerDictionary;
    public ExampleClass() {
        // Only required for Example #1
        readonlyInnerDictionary = new ReadOnlyDictionary<string, string>(innerDictionary);
    }   
    public IReadOnlyDictionary<string, string> GetExampleOne() {
        // Requires a second dictionary which is more boiler plate but the object being returned is truly readonly
        return readonlyInnerDictionary;     
    }
    public IReadOnlyDictionary<string, string> GetExampleTwo() {
        // Requires InnerDictionary be defined as Dictionary (Not IDictionary) but doesn't require the second dictionary be defined
        // which is less boiler plate, but the object returned could be re-cast to it's mutable form meaning it's not truly mutation safe.
        return innerDictionary;
    }
    public ImmutableDictionary<string, string> GetExampleThree() {
        // Truly immutable object returned, but a new instance is built for every call; fortunately all of my dictionaries are small (containing at most 9 keys)
        return innerDictionary.ToImmutableDictionary();
    }

选项1是可行的。您可以将ReadOnlyDictionary重铸为IDictionary,但是当尝试改变时将抛出异常:

 void CastingTest()
        {
            var dic1 = new Dictionary<string, string>();
            dic1.Add("Key", "Value");
            var dic2 = new ReadOnlyDictionary<string, string>(dic1);
            var castedDic = (IDictionary<string, string>)dic2;
            castedDic.Add("AnotherKey", "Another Value"); //System.NotSupportedException, Collection is read only
        }

ReadOnlyDictionary不创建另一个Dictionary。它指向与第一个相同的引用,封装了第一个。如果你这样做了:

void AddTest()
        {
            var dic1 = new Dictionary<string, string>();
            dic1.Add("Key", "Value");
            var dic2 = new ReadOnlyDictionary<string, string>(dic1);
            dic1.Add("Key2", "Value2"); //Now dic2 have 2 values too.
        }

认定最整洁、最便捷、最安全;但不是最高效的解决方案是在内部使用ConcurrentDictionary,以确保线程安全(从System.Collections.Concurrent),然后使用System.Collections.Immutable调用dictionary.ToImmutableDictionary(),它创建了逃避内部类的字典。接口签名为ImmutableDictionary<KeyType, ValueType>

这不是性能最好的解决方案,但在我的情况下,字典少于12个键和小的简单对象表示状态,在大多数情况下,这不是一个问题。

最新更新