c#安全地返回字典引用
本文关键字:字典 引用 返回 安全 | 更新日期: 2023-09-27 18:05:10
考虑到代码安全性和对代码可读性/视觉性的影响,我正在考虑三种方法来返回内部字典实例(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个键和小的简单对象表示状态,在大多数情况下,这不是一个问题。