C# 自调用匿名函数
在JavaScript中,经常会看到自调用函数:C# 自调用匿名函数,c#,anonymous-function,anonymous-methods,self-invoking-function,C#,Anonymous Function,Anonymous Methods,Self Invoking Function,在JavaScript中,经常会看到自调用函数: var i = (function(x) { return x; })(42); // i == 42 虽然我肯定不会比较语言,但我认为这样的构造可以翻译为C#,提供了支持的语言版本: var i = (delegate(int x) { return x; })(42); 或: 甚至: var i = (x => x)(42); 但是,每个版本都有错误: 应为方法名 是否不支持自调用匿名方法(由于显式禁止或类型推断
var i = (function(x) {
return x;
})(42);
// i == 42
虽然我肯定不会比较语言,但我认为这样的构造可以翻译为C#,提供了支持的语言版本:
var i = (delegate(int x) {
return x;
})(42);
或:
甚至:
var i = (x => x)(42);
但是,每个版本都有错误:
应为方法名
是否不支持自调用匿名方法(由于显式禁止或类型推断的不可能性),或者我的尝试中是否存在错误
我大胆猜测,因为没有方法声明(Func
)可以推断类型,所以它无法对隐含类型进行排序,因为我想按名称调用声明的方法,而且语法真的搞错了
勘误表 在这个问题被淹没之前:
var i = new Func<int, int>(x => x)(42);
var x=((Func)(y=>y*2))(10);
问题是,当编译器看到
y=>y*2
时,默认情况下会将其分类为表达式,而不是Func
,除非有上下文信息让它知道它应该是Func
。通过将它转换为Func
我们为它提供了所需的上下文。我想C团队的人可以给出更好的答案,但我尝试了我的方法。这里的问题不是这是否是一个最佳实践,而是它是否可能,如果不可能,为什么
让我们从你要写的内容开始:
var i = (x => x)(42);
非常简单,您将一个整数(42
)传递给lambda,它对其进行处理并返回相同的值。它的参数是一个整数(从其用法推断),它返回一个整数(从表达式推断),而i
是另一个整数(从返回值推断)
不幸的是,这在第一步就被打破了。让我:
编译器试图根据使用lambda表达式的上下文计算出lambda表达式的参数类型
这是什么意思?实际上,编译器需要一些信息,但它只能使用:
- 像
(Func)(x=>x))
或newfunc(x=>x)
中那样的显式强制转换、构造函数或声明。此处所需的类型是使用所需的最终类型给出或推断的
- 赋值(同样是因为可以推断最终类型),如:
Func f=(x=>x)代码>
在您的情况下,编译器必须从其参数推断函数类型,这是不可能的,因为参数是根据表达式验证的,反之亦然
为什么这在C#中不可能?因为(x=>x)
只是一个委托,那么它可以是接受整数参数的任何委托(如果我们假设编译器可以从rhs推断lhs并根据lhs验证rhs)并返回另一个整数。实际上,在C#中不允许在委托之间进行转换,因此表达式无效(即使此特殊委托不会分配给任何变量,并且将来也不会使用)。它可以是Func
或Expression
或任何其他委托(对于bool
参数,它甚至可以是谓词
)
当然,这是一个C#设计决策,同样的表达式——例如——在VB.NET中是完全有效的:
Dim i = (Function(x) x)(42)
不同的语言,不同的规则需要遵守,C#的目标是避免这种歧义。考虑一下为什么您需要javascript中的这种结构,并将这种概念应用到C#。asawyer虽然我欣赏对您的评论采用“教人钓鱼”的方法,但还是希望您能稍加阐述;)在javascript中,自调用函数究竟能实现什么?@Brandon我想,关键是它是否是一件好事。如果您编写一个长的匿名函数,那么如果您编写一个真正命名的函数,您的代码可能会更清晰。@Bracketworks所以您需要一个可以包含私有变量值的对象,它可以公开属性和其他函数?我认为在c#…vari=newfunc(x=>x)(42)中有一个词来表示这种类型的构造代码>语法也是有效的。@Caramiriel:啊,是的,我从来没有考虑过使用构造函数语法:),如果确实是这样的话;编译器看到x=>x
并将其解释为一个表达式,那么为什么委托
替代方案不起作用呢?@Bracketworks:我认为这是因为用delegate
声明的匿名方法在分配给某个对象之前不是完全类型化的。同样,它需要上下文。这项工作:((Func)委托(inty){returny y*2;})(10)代码>。看见
var x = ((Func<int, int>)(y => y * 2))(10);
var i = (x => x)(42);
Dim i = (Function(x) x)(42)