Rob*_*ers 185 .net dictionary readonly
我在我的只读属性中返回对字典的引用.如何防止消费者更改我的数据?如果这是一个IList我可以简单地返回它AsReadOnly.我能用字典做些什么吗?
Private _mydictionary As Dictionary(Of String, String)
Public ReadOnly Property MyDictionary() As Dictionary(Of String, String)
Get
Return _mydictionary
End Get
End Property
Run Code Online (Sandbox Code Playgroud)
Jef*_*tes 230
.NET Framework 4.5 BCL介绍ReadOnlyDictionary<TKey, TValue>(源代码).
由于.NET Framework 4.5 BCL不包含AsReadOnlyfor词典,因此您需要编写自己的(如果需要).它将类似于以下内容,其简单性可能突出了它为什么不是.NET 4.5的优先级.
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary)
{
return new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
Run Code Online (Sandbox Code Playgroud)
在.NET 4.5之前,没有.NET框架类包装Dictionary<TKey, TValue>类似于ReadOnlyCollection包装List.但是,创建一个并不困难.
这是一个例子 - 如果你是谷歌的ReadOnlyDictionary,还有很多其他的.
Tho*_*que 156
这是一个包装字典的简单实现:
public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
#region IDictionary<TKey,TValue> Members
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw ReadOnlyException();
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return _dictionary.Keys; }
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw ReadOnlyException();
}
public bool TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return _dictionary.Values; }
}
public TValue this[TKey key]
{
get
{
return _dictionary[key];
}
}
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
return this[key];
}
set
{
throw ReadOnlyException();
}
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw ReadOnlyException();
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw ReadOnlyException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _dictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_dictionary.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _dictionary.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw ReadOnlyException();
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
private static Exception ReadOnlyException()
{
return new NotSupportedException("This dictionary is read-only");
}
}
Run Code Online (Sandbox Code Playgroud)
kno*_*cte 19
在最近的BUILD会议上宣布,自.NET 4.5以来,System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>包含了界面.证明在这里(单声道)和这里(微软);)
不确定是否ReadOnlyDictionary也包括在内,但至少在界面上创建一个暴露官方.NET通用接口的实现应该不难.
Dal*_*ard 18
随意使用我的简单包装.它不实现IDictionary,因此它不必在运行时为可能更改字典的字典方法抛出异常.改变方法根本不存在.我为它创建了自己的界面,名为IReadOnlyDictionary.
public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable
{
bool ContainsKey(TKey key);
ICollection<TKey> Keys { get; }
ICollection<TValue> Values { get; }
int Count { get; }
bool TryGetValue(TKey key, out TValue value);
TValue this[TKey key] { get; }
bool Contains(KeyValuePair<TKey, TValue> item);
void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex);
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
}
public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
readonly IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); }
public ICollection<TKey> Keys { get { return _dictionary.Keys; } }
public bool TryGetValue(TKey key, out TValue value) { return _dictionary.TryGetValue(key, out value); }
public ICollection<TValue> Values { get { return _dictionary.Values; } }
public TValue this[TKey key] { get { return _dictionary[key]; } }
public bool Contains(KeyValuePair<TKey, TValue> item) { return _dictionary.Contains(item); }
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _dictionary.CopyTo(array, arrayIndex); }
public int Count { get { return _dictionary.Count; } }
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dictionary.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return _dictionary.GetEnumerator(); }
}
Run Code Online (Sandbox Code Playgroud)
Nea*_*eal 11
IsReadOnly on IDictionary<TKey,TValue>继承自ICollection<T>(IDictionary<TKey,TValue>extends ICollection<T>as ICollection<KeyValuePair<TKey,TValue>>).它不以任何方式使用或实现(实际上通过使用显式实现关联ICollection<T>成员来"隐藏" ).
我可以通过至少3种方式来解决问题:
IDictionary<TKey, TValue>和包装/委托给内部字典ICollection<KeyValuePair<TKey,
TValue>>集合返回
为只读或
IEnumerable<KeyValuePair<TKey,
TValue>>取决于值的使用.ctor(IDictionary<TKey,
TValue>)并返回副本 - 这样用户可以随意使用它,并且它不会影响托管源字典的对象的状态.请注意,如果要克隆的字典包含引用类型(不是示例中所示的字符串),则需要"手动"复制并克隆引用类型.作为旁白; 在暴露集合时,旨在暴露最小的可能接口 - 在示例中它应该是IDictionary,因为这允许您在不破坏类型公开的公共合同的情况下改变底层实现.
只读字典可以在某种程度上替换为Func<TKey, TValue>- 如果我只希望人们执行查找,我通常在API中使用它.它很简单,特别是,如果您愿意,更换后端很简单.但是,它没有提供密钥列表; 这是否重要取决于你在做什么.