经常困扰我的一件事是,执行此非常简单(对于我的工作,非常常见)的操作需要花费几行代码:
var lTheDict = new Dictionary<string, object>();
// The dictionary gets some stuff put in it elsewhere...
// Do annoying lookup that must be common but is always unwieldy.
object lTheObject;
int lTheValue; // NOTE: Not always an int
if (lTheDict.TryGetValue("TheKey", out lTheObject))
{
lTheValue = (int) lTheObject;
}
我确信必须有更好的方法来执行此操作,也许可以使用null合并或其他方法。我真正想要写的东西是这样的:
int lTheValue ?= (int) lTheDict["TheKey"];
换句话说,如果TheKey存在,请给我取值,否则请给我“空”整数。
几乎不可能刮掉线条。即使我们只是尝试查找并广播并在单行“捕获并忽略”中捕获异常(我的工作场所代码样式均不允许这样做),我们仍然必须 在try块外声明变量,并以类似以下内容结束:
int lTheValue;
try {
lTheValue = (int) lTheDict["TheKey"];
} catch (Exception ex) { }
这又是一个荒谬的开销代码,掩盖了应该是显而易见的操作。
即使只是能够摆脱lTheObject的声明,只要在我们将其用作outparam(在.NET 5或我听到的东西中使用它)时进行声明即可删除一行。这些函数本身的长度通常只有10行,并且看起来我们在对该集合进行一些重要的工作,因为一半的代码专用于获取值,但实际上这只是一种干扰。
注意::我知道我可以编写一个模板化函数来执行此操作,但是即使在该函数中,也不得不再次编写这些行。一定有更好的方法!
有没有人发现或者您能想到一种较短的书写方式?
答案 0 :(得分:4)
static class MyExtensions
{
public static T MagicGet<T>(
this Dictionary<string, object> lookup,
string key)
{
return lookup.TryGetValue(key, out var value)) ? (T)value : default(T);
}
}
...
var value = lTheDict.MagicGet<int?>("TheKey");
或者不创建扩展名,您可以像这样简单地编写原始查询:
int lTheValue = lTheDict.TryGetValue("TheKey", out object lTheObject) ? (int) lTheObject : default(int);
答案 1 :(得分:1)
我在大多数代码中都定义了这两种扩展方法:
public static Func<K, V> Map<K, V>(this IDictionary<K, V> source, Func<V> @default)
{
return key => (key == null || !source.ContainsKey(key)) ? @default() : source[key];
}
public static Func<K, V> Map<K, V>(this IDictionary<K, V> source, Func<K, V> @default)
{
return key => (key == null || !source.ContainsKey(key)) ? @default(key) : source[key];
}
然后您可以执行以下操作:
Dictionary<string, object> lTheDict = new Dictionary<string, object>();
Func<string, object> mapTheDict = lTheDict.Map(k => (int?)null);
object lTheValue = mapTheDict("TheKey");
这里有趣的是,您可以使用lambda返回基于键本身的默认值。我发现这非常有用-特别是对于调试。