在尝试使用ForEach调用键之前,检查键是否存在于Action's字典中
本文关键字:Action 存在 字典 是否 ForEach 调用 检查 | 更新日期: 2023-09-27 18:06:03
我有一个字典,其中键是一个字符串,值是一个动作。设置字符串键到函数的映射。然后我有一个列表,我调用。foreach(),并在其中使用列表中的值作为键,然后调用与之相关的函数。如果密钥不存在,问题就会出现。我如何在。foreach函数中检查这一点?我想使用三元运算符,但它似乎不起作用。
private Dictionary<string, Func<IniConfig, object>> typeMapping = new Dictionary<string, Func<IniConfig, object>>();
typeMapping["MB"] = ProcessMB;
public object ProcessMB(IniConfig file)
{
return null;
}
object iif(bool expression, object truePart, object falsePart)
{ return expression ? truePart : falsePart; }
FilesToProcess.ForEach(x => iif(typeMapping.ContainsKey(x.ExtractType), typeMapping[x.ExtractType](x), Error(x)));
这突出显示了iif()调用中带有error的第二个形参:参数2:不能从'void'转换为'object', error (x)部分也是如此。
似乎三元操作符返回一个对象?因此,如果我将Action更改为Func并将返回类型为对象并使我的函数返回它编译的对象,但是当我使用无效键运行测试时,它不会进入我的Error()函数,它会抛出"给定键不存在于字典中"异常。我希望它执行三元操作,并看到typeMapping没有键,因此无法执行Error()函数。我错过了什么?
您的iif()
方法在这里是反直觉的,并且看起来像是过度使用LINQ。下面是我要做的:
foreach (var file in filesToProcess)
{
Func<IniConfig, object> action;
if (typeMapping.TryGetValue(file.ExtractType, out action))
{
action(file);
}
else
{
Error(file);
}
}
让你的代码更容易阅读:)
编辑:我已经找到了一种通用的方法来做你想做的事。首先,您需要为
IDictionary<TKey,TVal>
创建一个扩展方法,如果键不存在,它只返回默认值:
public static TVal GetValueOrDefault<TKey, TVal>(this IDictionary<TKey, TVal> self, TKey key)
{
TVal ret;
self.TryGetValue(key, out ret);
return ret;
}
那么你可以使用空合并(??
)运算符:
FilesToProcess.ForEach((typeMapping.GetValueOrDefault(x.ExtractType) ?? Error)(x));
让您的生活变得简单,只需创建一个小的辅助函数来做您想做的事情:
private void InvokeProcessor(IniConfig iniConfig)
{
Func<IniConfig, object> processor;
if (typeMapping.TryGetValue(x.ExtractType, out processor)
processor(iniConfig);
else
Error(iniConfig);
}
然后像这样使用:
FilesToProcess.ForEach(InvokeProcessor);
易于阅读和理解。而且更快,因为每个文件只需要搜索一次字典。
编辑
好吧,如果你真的想使用奇怪的iif()
,这里是如何修复它:
object iif(bool expression, Func<object> truePart, Func<object> falsePart)
{ return expression ? truePart() : falsePart(); }
…以及如何使用它:
FilesToProcess.ForEach(x => iif(
typeMapping.ContainsKey(x.ExtractType),
() => typeMapping[x.ExtractType](x),
() => Error(x)));
基本上iif()
的2和和3rd参数的求值是延迟的,直到其中一个是实际需要的。在以前的版本中,所有参数都在执行iff()
之前求值,导致每次处理IniConfig
对象时调用字典索引器和调用Error()
。
一个警告:如果你在生产中使用这个,那么harakiri可能是你唯一的出路,它将在几年后战胜你。