I want a dictionary that would return a specified value for any key not in the开发者_Go百科 dictionary, something like:
var dict = new DictWithDefValues("not specified");
dict.Add("bob78", "Smart");
dict.Add("jane17", "Doe");
Assert.AreEqual(dict["xxx"], "not specified");
Extending System.Collections.Generics.Dictionary and overriding TryGetValue doesn't work because TryGetValue isn't virtual.
Reimplementing Dictionary from scratch (from IDictionary<,>) is too much efforts.
Extension method won't let me "initialize" the dictionary with a default value. I want the consumer of dictionary to think that key is there, not just do dict.GetOrDefault(key, "not specified");
Reimplementing Dictionary from scratch (from IDictionary<,>) is too much efforts
This is really the best option. Just encapsulate a Dictionary<,>
as a member of your class, and pass all members to the Dictionary's code. You only need to handle the properties and methods you wish to be different in that case.
I agree that it's a bit of tedious work - but it's probably less than 5 minutes worth of typing, since every method can be passed to the internal dictionary's implementation.
I think Reed is correct that Reimplementing Dictionary is pretty simple and if that's what you need that's fine.
but it still seems like overkill to create a new class to replace
dict.TryGetValue("xxx", out value);
value = value ?? "not specified";
with
value = dict.GetOrDefault(key, "not specified")
This extension method gets me through;
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, TValue defaultValue = default(TValue))
{
TValue found;
if (source.TryGetValue(key, out found))
{
return found;
}
else
{
return defaultValue;
}
}
It's called like so;
dict.GetValueOrDefault("foo", 0) // returns the key under "foo", or 0 if missing.
I created a DefaultableDictionary in .NET that does exactly what you are asking for!
http://github.com/jsonmez/Defaultable-Dictionary
Blog post here.
Try this
public class DefaultDictionary<Tkey,Tvalue>
where Tkey: IEquatable<Tkey>
{
private readonly Func<Tvalue> _getDefault;
private Dictionary<Tkey, Tvalue> _dict;
public DefaultDictionary(Func<Tvalue> getDefault = null)
{
if (getDefault == null)
{
_getDefault = () => default(Tvalue);
}
else
{
_getDefault = getDefault;
}
_dict = new Dictionary<Tkey, Tvalue>();
}
public Tvalue this[Tkey key]
{
get
{
if (!_dict.ContainsKey(key))
{
_dict[key] = _getDefault();
}
return _dict[key];
}
set { _dict[key] = value; }
}
public bool ContainsKey(Tkey key)
{
return _dict.ContainsKey(key);
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var kvp in _dict)
{
sb.AppendFormat("[{0}] : {1}", kvp.Key.ToString(), kvp.Value.ToString()).AppendLine();
}
return sb.ToString();
}
}
You can easily add wrappers to the other methods and properties as needed.
I notice your example is a dictionary of Strings. It is also strings in my own scenario where I want similar behavior.
Perhaps the good old StringDictionary
class will do what you want. Unlike Dictionary<string,string>
its get_Item method returns null
for keys which do not exist in the dictionary.
精彩评论