相当于 Python 的 get() 方法的 C# 字典
C# Dictionary equivalent to Python's get() method
在 Python 中,如果我有一个字典,并且我想从一个可能不存在键的字典中获取一个值,我会做类似的事情:
lookupValue = somedict.get(someKey, someDefaultValue)
其中,如果 someKey
不存在,则返回 someDefaultValue
。
在 C# 中,TryGetValue()
有点类似:
var lookupValue;
if(!somedict.TryGetValue(someKey, lookupValue))
lookupValue = someDefaultValue;
不过有一个问题是,如果 someKey
是 null
,则会抛出一个异常,因此您要进行空检查:
var lookupValue = someDefaultValue;
if (someKey != null && !somedict.TryGetValue(someKey, lookupValue))
lookupValue = someDefaultValue;
老实说,这很恶心(字典查找需要 3 行?)是否有更简洁(即 1 行)的方式很像 Python 的 get()
?
TryGetValue 不是您要查找的方法。此方法 returns 一个布尔值。如果找到密钥则为真,如果找到则为假 not.Anf 如果找到密钥,它将把值设置为您选择的变量。你要的方法,字典里没有class。
所以你有两个选择来解决这个问题:
检查是否存在:
var value;
if (somedic.TryGetValue("key", out value))
lookupValue = value;
else
lookupValue = defaultValue;
创建您自己的方法,如 blog 中所示。
下面是TryGetValue
的正确使用方法。请注意,您不能在调用 TryGetValue
之前将 return 值设置为默认值,而只是 return 它,因为如果找不到密钥, TryGetValue
会将其重置为默认值.
public static TValue GetOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultValue)
{
TValue value;
if(key == null || !dictionary.TryGetValue(key, out value))
return defaultValue;
return value;
}
当然,如果键是 null
,您实际上可能想要一个例外,因为对于字典来说,这始终是无效键。
现在可以使用 C# 7.0 内联输出变量声明将其简化为以下内容。
return key == null || !dictionary.TryGetValue(key, out var value)
? defaultValue
: value;
随着 C# 语言从 7.1 开始对 lambda 和默认值以及 8 对可空性进行了更多改进,Get() 函数现在可以写成
public static class Extentions
{
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
[return: NotNullIfNotNull("defaultValue")]
public static TValue? Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue? defaultValue = default)
=> key == null || !dictionary.TryGetValue(key, out var value) ? defaultValue : value;
/// <summary>
/// Gets the value associated with the specified key and box/un-box correctly.
/// </summary>
[return: NotNullIfNotNull("defaultValue")]
public static TTarget? GetWithConversion<TTarget, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TTarget? defaultValue = default) where TTarget : TValue
=> (TTarget?)Convert.ChangeType(Get(dictionary, key, defaultValue), typeof(TTarget?), CultureInfo.InvariantCulture);
}
给出与重载 Python 等效项大致相同的行为。我也在使用 GetWithConversion 来处理对象 boxing/unboxing.
参考:
=> expression body, NotNullIfNotNull,
default,
Nullable reference types
在 Python 中,如果我有一个字典,并且我想从一个可能不存在键的字典中获取一个值,我会做类似的事情:
lookupValue = somedict.get(someKey, someDefaultValue)
其中,如果 someKey
不存在,则返回 someDefaultValue
。
在 C# 中,TryGetValue()
有点类似:
var lookupValue;
if(!somedict.TryGetValue(someKey, lookupValue))
lookupValue = someDefaultValue;
不过有一个问题是,如果 someKey
是 null
,则会抛出一个异常,因此您要进行空检查:
var lookupValue = someDefaultValue;
if (someKey != null && !somedict.TryGetValue(someKey, lookupValue))
lookupValue = someDefaultValue;
老实说,这很恶心(字典查找需要 3 行?)是否有更简洁(即 1 行)的方式很像 Python 的 get()
?
TryGetValue 不是您要查找的方法。此方法 returns 一个布尔值。如果找到密钥则为真,如果找到则为假 not.Anf 如果找到密钥,它将把值设置为您选择的变量。你要的方法,字典里没有class。 所以你有两个选择来解决这个问题:
检查是否存在:
var value; if (somedic.TryGetValue("key", out value)) lookupValue = value; else lookupValue = defaultValue;
创建您自己的方法,如 blog 中所示。
下面是TryGetValue
的正确使用方法。请注意,您不能在调用 TryGetValue
之前将 return 值设置为默认值,而只是 return 它,因为如果找不到密钥, TryGetValue
会将其重置为默认值.
public static TValue GetOrDefault<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary,
TKey key,
TValue defaultValue)
{
TValue value;
if(key == null || !dictionary.TryGetValue(key, out value))
return defaultValue;
return value;
}
当然,如果键是 null
,您实际上可能想要一个例外,因为对于字典来说,这始终是无效键。
现在可以使用 C# 7.0 内联输出变量声明将其简化为以下内容。
return key == null || !dictionary.TryGetValue(key, out var value)
? defaultValue
: value;
随着 C# 语言从 7.1 开始对 lambda 和默认值以及 8 对可空性进行了更多改进,Get() 函数现在可以写成
public static class Extentions
{
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
[return: NotNullIfNotNull("defaultValue")]
public static TValue? Get<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue? defaultValue = default)
=> key == null || !dictionary.TryGetValue(key, out var value) ? defaultValue : value;
/// <summary>
/// Gets the value associated with the specified key and box/un-box correctly.
/// </summary>
[return: NotNullIfNotNull("defaultValue")]
public static TTarget? GetWithConversion<TTarget, TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TTarget? defaultValue = default) where TTarget : TValue
=> (TTarget?)Convert.ChangeType(Get(dictionary, key, defaultValue), typeof(TTarget?), CultureInfo.InvariantCulture);
}
给出与重载 Python 等效项大致相同的行为。我也在使用 GetWithConversion 来处理对象 boxing/unboxing.
参考: => expression body, NotNullIfNotNull, default, Nullable reference types