如何更改字典的工作方式,以便如果没有具有给定键的 KVP,它返回默认值,而不用dic["nonexistentKey"]
try-catch 包装通常?
问问题
273 次
4 回答
6
您可以创建自己的类来封装aDictionary<TKey,TValue>
并实现IDictionary<TKey,TValue>
.
这将像字典一样,但您可以编写行为以任何您希望的方式处理不存在的键。
但是,您无法更改实际Dictionary<TKey,TValue>
类的运行方式。
于 2012-10-30T16:17:47.987 回答
5
如果您愿意,还可以向 IDictionary 或 Dictionary 添加扩展方法。
public static class IDictionaryExtensions
{
public static TValue ValueAtOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
{
if (dictionary == null || !dictionary.ContainsKey(key))
{
return defaultValue;
}
return dictionary[key];
}
}
请注意,如果字典为空,您可能想要抛出一个ArgumentNullException
,而不是像示例中那样返回默认值......任何适合您的东西。
于 2012-10-30T16:19:26.973 回答
3
Dictionary<int, YourType> dictionary = ...;
YourType x;
if (!dictionary.TryGetValue(123, out x))
{
x = new YourType();
}
// here X will be assigned to the value or the default if the key was not present.
如果您确实需要覆盖默认dictionary[key]
方法,则可以使用此类(作为字典本身或作为现有字典的包装器):
/// <summary>
/// A dictionary implementation that returns the default value of <typeparamref name="TValue"/> when the key is not present in the dictionary.
/// </summary>
public class DictionaryWithDefaults<TKey, TValue> : IDictionary<TKey, TValue>
{
/// <summary>
/// Holds the actual data using standard dictionary.
/// </summary>
private IDictionary<TKey, TValue> _storage;
/// <summary>
/// Initializes a new instance of the <see cref="DictionaryWithDefaults{TValue}" /> class.
/// The data is stored directly in this dictionary.
/// </summary>
public DictionaryWithDefaults()
{
this._storage = new Dictionary<TKey, TValue>();
}
/// <summary>
/// Initializes a new instance of the <see cref="DictionaryWithDefaults{TValue}" /> class.
/// This dictionary acts as a wrapper for the data stored in the dictionary <paramref name="forWrapping" />.
/// </summary>
/// <param name="forWrapping">The dictionary object for wrapping.</param>
/// <exception cref="System.ArgumentNullException">when <paramref name="forWrapping"/> is <c>null</c></exception>
public DictionaryWithDefaults(IDictionary<TKey, TValue> forWrapping)
{
if (forWrapping == null)
throw new ArgumentNullException("forWrapping");
this._storage = forWrapping;
}
public void Add(TKey key, TValue value)
{
this._storage.Add(key, value);
}
public bool ContainsKey(TKey key)
{
return this._storage.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return this._storage.Keys; }
}
public bool Remove(TKey key)
{
return this._storage.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
// always return a value, even if the key does not exist.
// this is also the only place one would modify if the default value has to be customized (passed in the constructor etc.)
if (!this._storage.TryGetValue(key, out value))
value = default(TValue);
return true;
}
public ICollection<TValue> Values
{
get { return this._storage.Values; }
}
public TValue this[TKey key]
{
get
{
TValue value;
this.TryGetValue(key, out value);
return value;
}
set
{
this._storage[key] = value;
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
this._storage.Add(item);
}
public void Clear()
{
this._storage.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return this._storage.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
this._storage.CopyTo(array, arrayIndex);
}
public int Count
{
get { return this._storage.Count; }
}
public bool IsReadOnly
{
get { return this._storage.IsReadOnly; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return this._storage.Remove(item);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return this._storage.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this._storage.GetEnumerator();
}
}
于 2012-10-30T16:22:27.670 回答
1
不,你必须把它包起来。this[]
不是虚拟方法,不能被覆盖。
所以你最好的选择是创建一个简单的类,它公开IDictionary
(或仅选定的方法)并this[] get
用 try/catch 包装。
于 2012-10-30T16:19:04.503 回答