C# 是否存在任何类型的通用字典,试图获取不存在的密钥将返回null?
我必须使用C# 是否存在任何类型的通用字典,试图获取不存在的密钥将返回null?,c#,.net,dictionary,C#,.net,Dictionary,我必须使用.ContainsKey而不是仅仅在字典中使用value==null,这让我非常恼火。现实生活中的例子: var dictionary = new Dictionary<string, FooBar>(); var key = "doesnt exist"; var tmp = dictionary[key] ?? new FooBar(x, y); 或者这个: FooBar tmp = null; if (!Dictionary.TryGetValue(key, out
.ContainsKey
而不是仅仅在字典中使用value==null
,这让我非常恼火。现实生活中的例子:
var dictionary = new Dictionary<string, FooBar>();
var key = "doesnt exist";
var tmp = dictionary[key] ?? new FooBar(x, y);
或者这个:
FooBar tmp = null;
if (!Dictionary.TryGetValue(key, out tmp))
{
tmp = new FooBar(x, y);
}
对我来说,这段代码非常冗长。是否有一个内置泛型类实现IDictionary(或以其他方式允许键值类型访问),但在我尝试查找键时不会引发异常,而是返回null 问题在于
字典
允许您将null
存储为一个值,这样您就不知道该键是否不存在,或者该键的值是否为null
。另一个问题是null
仅对作为引用类型(或null
)的TValue
类型有效
现在,也就是说,您可以自己编写一个扩展方法来实现这一点:
public static class DictionaryUtilities
{
public static TValue SafeGet<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultIfNotFound = default(TValue))
{
TValue value;
return dict.TryGetValue(key, out value) ? value : defaultIfNotFound;
}
}
公共静态类字典实用性
{
公共静态TValue SafeGet(此字典dict,TKey键,TValue defaultIfNotFound=默认值(TValue))
{
t价值;
返回dict.TryGetValue(key,out value)?值:defaultIfNotFound;
}
}
通过这种方式,您可以按如下方式查询词典:
var sample = new Dictionary<int, string> { {1, "One"}, {2, "Two}, {3, "Three"} };
var willBeNull = sample.SafeGet(4);
var willBeHi = sample.SafeGet(4, "HI!");
var-sample=新字典{{1,“一”},{2,“二”},{3,“三”};
var willBeNull=sample.SafeGet(4);
var willBeHi=sample.SafeGet(4,“嗨!”);
当然,如果TValue
是值类型,则上述代码将返回值类型的默认值(也就是说,如果值类型是int
,则默认情况下,未找到时将返回0
)
同样,您可以创建两种形式,一种是
TValue
被约束为class
,另一种是struct
,允许您为值类型返回null
。对于泛型集合null
并不总是有效的值,您无法编写返回如果确定不会将其用作值,则可以轻松创建一个返回默认值(T)的实用程序方法。如果扩展,则每次都必须传递一个默认值。
这可能就是你想要的。
可以实现字典并在ctor中传递默认值
public class DictionaryWithDefault<T1,T2> : Dictionary<T1,T2>
{
private T2 t2Default;
public new T2 this[T1 t1]
{ // indexer - if the key is not present return the default
get
{
T2 t2t;
return TryGetValue(t1, out t2t) ? t2t : t2Default;
}
set {
base[t1] = value;
}
}
public DictionaryWithDefault(T2 _t2) { this.t2Default = _t2; }
}
公共类字典WithDefault:Dictionary
{
私人违约;
公共新T2本[T1]
{//索引器-如果键不存在,则返回默认值
得到
{
t2t;
返回TryGetValue(t1,out t2t)?t2t:t2默认值;
}
设置{
基[t1]=值;
}
}
公共字典WITHDEFAULT(T2_T2){this.t2Default=_T2;}
}
如果希望字典不允许值为null,则重写Add
借用了jamesh+1的一些语法
我使用的是一个带有复合键的字典
如果更改了默认值,则会更改默认值。我正在做这件事。
如果T2是一种值类型,那么它可以工作。
如果T2是引用类型,则需要进行深度复制,不值得这么麻烦。为什么不创建自己的扩展方法?字典是这样工作的,因为包含null值和根本不包含值之间有区别。您需要两种类型的null。否则您无法区分sh值是否为null或值是否不存在您可能可以创建一个单独的参数
TryGetValue
扩展方法,其行为如您所描述的。这太糟糕了TryGetValue
使用out
参数而不是ref
,并且在键不存在时不能简单地将变量单独保留,siNCE可以简单地初始化具有期望缺省值的变量。如果你的目标是在字典中添加一个项目,如果它不存在,你可能会考虑<代码> CONTURNECTORION < /COD>,它有一些有趣的<代码> GETORADOD>代码>方法。<代码> Outs< /Cord>关键字保证变量被初始化。所以<代码>?这里不需要ode>运算符。只有三行:declare x;TryGet(out x);return x;
@abatishchev:dependens,如果我们想要一个用户指定的默认值,我们需要在调用后设置它,因为out
会将它踩死。我认为更好的解决方案是以某种方式限制它,这样,如果你想提供一个默认值,那么你只能使用可为空类型的扩展方法-是。否则它将ave justdefault(T)
,正如您在可选参数中提到的那样。@Earlz:True,不管重点是什么,OP都可以自由地创建他们喜欢的任何风格的方法。
public class DictionaryWithDefault<T1,T2> : Dictionary<T1,T2>
{
private T2 t2Default;
public new T2 this[T1 t1]
{ // indexer - if the key is not present return the default
get
{
T2 t2t;
return TryGetValue(t1, out t2t) ? t2t : t2Default;
}
set {
base[t1] = value;
}
}
public DictionaryWithDefault(T2 _t2) { this.t2Default = _t2; }
}