C#语言规范 6.5匿名函数转换指出:
...
具体来说,匿名函数F与提供的委托类型D兼容:
...
如果F不包含 anonymous-function-signature ,则D可能具有 零个或多个任何类型的参数,只要D的参数没有 out参数修饰符。
但是,以下代码会产生错误。
using System;
namespace DelegateAnonymousFunctionExample
{
public delegate void D(int i, int b);
class Program
{
static void Main(string[] args)
{
// Valid
D f1 = (int a, int b) =>
{
Console.WriteLine("Delegate invoked...");
};
f1(3, 4);
// Error
D f2 = () =>
{
Console.WriteLine("Delegate invoked...");
};
Console.ReadKey();
}
}
}
以上代码在哪里出错?
答案 0 :(得分:2)
f2
变量未收到有效的方法签名,您委托D
正在等待2个参数。
答案 1 :(得分:1)
委托是一种类型,它表示对具有特定参数列表和返回类型的方法的引用
原则上,所有内容都从delegate
开始,并表示特定参数列表和返回类型。
如果F不包含匿名函数签名,则D可能具有 零个或多个任何类型的参数,只要D的参数没有 out参数修饰符。
可以使用语法delegate
parameter-list {
statement-list }
声明匿名方法。在这种情况下,您可以在上面省略 parameter-list 的情况。另一方面,如果您提供参数,则参数类型必须完全匹配。
public delegate void MyDelegate(int a);
MyDelegate d = delegate { }; //valid
MyDelegate d = delegate(int a) { }; //valid
MyDelegate d = delegate(int a, int b) { }; //invalid
public delegate void MyDelegateOut(int a, out int b);
MyDelegateOut d = delegate { }; //invalid
如果您想使用lambda声明delegate
,则无法存储省略效果,因为语法为( input-parameters )=>
{
语句列表 }
答案 2 :(得分:0)
6.5美元的价格规格还说:
表达式没有类型,但可以隐式转换为 兼容的委托类型或表达式树类型
和$ 6.5.1:
将匿名函数转换为委托类型会产生一个 引用匿名函数的委托实例
可以使用lambda-expression定义匿名方法, 实际上,这些事情是不同的。
Lambda expression没有类型,可以隐式转换为Expression查询表达式和LINQ方法定义中使用的Anonymous。
因此,在您的错误情况下,lambda表达式将转换为不接受参数的不兼容的委托实例。
您提供的规格中的报价说
D f5 = delegate { Console.WriteLine("Delegate invoked..."); };
它之所以有效,是因为没有指向签名,它将被自动编译为接受(int,int)的兼容委托实例。
“如果F不包含匿名函数签名” 表示缺少签名,但是lambda的'()'表示不接受参数的签名。正如@Johnny的答案中提到的那样,lambda不能没有签名就被声明。关于代表示例:请看代码示例中的第4个示例-该示例无效,因为具有不兼容的签名(不接受args),第5个示例没有签名并且有效。
您还可以在下面复制示例并检查其编译方式(请先注释无效的代码) https://sharplab.io/
public delegate void D(int i, int b);
public void Main(string[] args)
{
//valid, lambda expression will be converted to compatible delegate instance
D f1 = (int a, int b) => Console.WriteLine("Delegate invoked...");
f1(3, 4);
//INVALID, lambda expression will be converted to incompatible delegate instance
D f2 = () => Console.WriteLine("Delegate invoked...");
f2(3, 4);
//valid, assigning delegate with compatible signature
D f3 = delegate(int i, int j) { Console.WriteLine("Delegate invoked..."); };
f3(3, 4);
//INVALID, assigning delegate with incompatible signature
D f4 = delegate() { Console.WriteLine("Delegate invoked..."); };
f4(3, 4);
//valid, it will be automatically compiled to compatible delegate instance which accepts (int, int)
D f5 = delegate { Console.WriteLine("Delegate invoked..."); };
f5(3, 4);
}