Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否存在任何类型的通用字典,试图获取不存在的密钥将返回null?_C#_.net_Dictionary - Fatal编程技术网

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
并不总是有效的值,您无法编写返回的泛型方法ode>null。它必须是默认值(T)


如果确定不会将其用作值,则可以轻松创建一个返回默认值(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 just
default(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; }
}