Rag*_*dda 10 .net c# syntax lambda void
我有以下方法,我想知道是否有任何可以在下面的默认(void),因为有一个编译器错误,说这里的void无效:
private void applyDefaultsIfNecessary(ApplicationConfiguration configuration)
{
var defaults = new Dictionary<Predicate<ApplicationConfiguration>, Action<ApplicationConfiguration>>()
{
// { rule, action } - if rule is true, execute action
{ (c) => c.ConnectionString == null , (c) => c.ConnectionString = "foo" },
{ (c) => c.OutputExcelFilePath == null, (c) => c.ConnectionString = "bar" },
{ (c) => c.OutputDirectory == null, (c) => c.OutputDirectory = "baz" }
};
//Nothing to select, but we want to loop throough the dict and invoke action, if rule is true.
//It is a pity there is no extension method called DoForEach on collections.
defaults.Select((item) => item.Key.Invoke(configuration) ? item.Value.Invoke(configuration) : default(void) );
}
Run Code Online (Sandbox Code Playgroud)
我意识到我可以使用if-else语句而不是三元运算符(或者我可以调用一个虚方法来返回void).此外,Select扩展方法不喜欢返回void的lambda.似乎说不能推断出类型,但是当然如果我指定这样的类型,要么:
defaults.Select<ApplicationConfiguration, void>((item) => { if (item.Key.Invoke(configuration)) item.Value.Invoke(configuration); } );
Run Code Online (Sandbox Code Playgroud)
我从语言设计的角度来看很奇怪,为什么我们没有可以返回void的表达式或者无效的变量的数据类型.
Ree*_*sey 10
实际上,这违反了函数式编程规则.这与Eric Lippert描述的List.ForEach有同样的缺陷:你正在试图对你的收藏造成副作用.
Enumerable.Select旨在返回一个新集合 - 过滤输入.它不是为了执行代码.
话虽如此,您可以通过以下方式解决此问题:
defaults.Where(item => item.Key.Invoke(configuration)).ToList().ForEach( item => item.Value.Invoke(configuration));
Run Code Online (Sandbox Code Playgroud)
它没有做得那么明确:
var matches = defaults.Where(item => item.Key.Invoke(configuration));
foreach(var match in matches)
match.Value.Invoke(configuration);
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 10
我将引用您的规范7.1节,其中规定:
[表达式可以被分类为"无").当表达式是返回类型为void的方法的调用时,会发生这种情况. 分类为空的表达式仅在语句表达式的上下文中有效.
[强调补充].
也就是说,只有当表达式构成整个语句时,才可以使用表达式,这是一个返回void的方法.像这样:
M();
Run Code Online (Sandbox Code Playgroud)
首先,您真的应该避免在标准 linq 查询运算符中产生副作用,其次这实际上不起作用,因为您没有在任何地方枚举 Select 查询。如果你想使用 linq 你可以这样做:
foreach(var item in defaults.Where(i => i.Key.Invoke(configuration)))
{
item.Value.Invoke(configuration);
}
Run Code Online (Sandbox Code Playgroud)
关于您的问题,我很确定没有可能的 void 值,并且您无法明确返回它。在 F# 等函数式语言中,void 被替换为“单元”,即只有一个可能值的类型 - 如果您愿意,可以创建自己的单元类型并返回它。在这种情况下,您可以执行以下操作:
defaults.Select(item => {
if(item.Key.Invoke(configuration))
{
item.Value.Invoke(configuration);
}
return Unit.Value;
}).ToList();
Run Code Online (Sandbox Code Playgroud)
但我真的不建议这样做。