可能重复:
How to get null instead of the KeyNotFoundException accessing Dictionary value by key?
我目前在我的项目中有很多Dictionary<string, T>
次使用,其中大部分都是这样的:
if (myDic.ContainsKey("some key"))
localVar = myDic["some key"];
它也不是很有效,因为它会对字典进行两次调用,这可能会消耗资源。 TryGetValue()
是一件很酷的事情,但它不会在一行中完成。
如果null
没有此类密钥,我只想获得var v = myDic[key]
。我该怎么做?
答案 0 :(得分:4)
您可以使用TryGetValue
的扩展方法:
public static U GetValueByKeyOrNull<T, U>(this Dictionary<T, U> dict, T key)
where U : class
{
U value;
dict.TryGetValue(key, out value);
return value;
}
多亏了你能写的
somedict.GetValueByKeyOrNull("key1")
最后我试图做这件事,我想出了一个变体,使用了一个带有显式接口实现的字典类派生:How to get null instead of the KeyNotFoundException accessing Dictionary value by key?
那是
public interface INullValueDictionary<T, U>
where U : class
{
U this[T key] { get; }
}
public class NullValueDictionary<T, U> : Dictionary<T, U>, INullValueDictionary<T, U>
where U : class
{
U INullValueDictionary<T, U>.this[T key]
{
get
{
U val;
dict.TryGet(key, out val);
return val;
}
}
}
并在任何地方使用它而不是原始字典:
//create some dictionary
NullValueDictionary<int, string> dict = new NullValueDictionary<int, string>
{
{1,"one"}
};
//have a reference to the interface
INullValueDictionary<int, string> idict = dict;
string val = idict[2]; // null
val = idict[1]; // "one"
答案 1 :(得分:1)
我不喜欢处理null
因此我的实现将如下所示:
interface Maybe<T> {
bool HasValue {get;}
T Value {get;}
}
class Nothing<T> : Maybe<T> {
public bool HasValue { get { return false; } }
public T Value { get { throw new Exception(); } }
public static const Nothing<T> Instance = new Nothing<T>();
}
class Just<T> : Maybe<T> {
private T _value;
public bool HasValue { get { return true; } }
public T Value { get { return _value; } }
public Just(T val) {
_value = val;
}
}
Maybe
是一个可以包含或不包含值的对象。请注意,Nothing
类包含静态字段Instance
。每次我们需要从函数返回Nothing
时,我们都可以使用此值而不是创建新值。
现在,我们需要创建自己的字典类:
class MyDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> _dict;
...
public Maybe<TValue> this[TKey key] {
TValue val;
if (_dict.TryGetValue(key, out val)) {
return new Just<TValue>(val);
return Nothing<TValue>.Instance;
}
}
这种方法的优点尚不清楚,因为C#没有模式匹配。但可以使用dynamic
:
void ProcessResult(Just<string> val) {
Console.WriteLine(val);
}
void ProcessResult(Nothing<string> n) {
Console.WriteLine("Key not found");
}
var dict = new MyDictionary<string, string>();
...
dynamic x = dict["key"];
ProcessResult(x);
我认为这是非常明确的方式来表达字典不能总是返回有意义的结果。此外,对于读者来说,显然只会为字典中存在的值调用函数重载ProcessResult(Just<T>)
,并且在未找到键时将调用其他重载。
<强>优点:强>
<强>缺点:强>
答案 2 :(得分:0)
我决定这样做:
class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
public new TValue this[TKey key]
{
get
{
TValue value;
return TryGetValue(key, out value) ? value : default(TValue);
}
set { base[key] = value; }
}
}
它允许我像任何其他字典一样使用它,通过方括号。由于我不打算将值类型用作TValue
,我认为这是一个很好的解决方案。