jdu*_*tor 38 c# lambda async-await c#-5.0
阅读这篇关于C#5 async/await的一些问题的博客文章.它在Gotcha#4中提到了一些非常深刻的东西,而且我以前没想过.
简而言之,它涵盖了一个方法,其中有一个方法有两个重载,一个取一个Action,一个取一个Func<Task>(例如Task.Run).这个问题的根源在于async void方法应该仅用于事件处理程序,然后该帖子继续描述以下场景 - 编译器推断出什么时候像下面这样的lambda函数可以编译为a Func<Task>和a Action:
Task.Run(async () => {
await Task.Delay(1000);
});
Run Code Online (Sandbox Code Playgroud)
由于Task.Run既有的签名Task.Run(Func<Task>)和Task.Run(Action),是什么类型编译异步匿名函数?一个async void还是一个Func<Task>?我的直觉是它会编译成async void纯粹因为它是非泛型类型,但C#编译器可能很聪明并且给出了Func<Task>类型偏好.
另外,有没有办法明确声明我希望使用哪个重载?我知道我可以创建一个新的实例Func<Task>并在那里传递异步lambda函数,但它仍然会编译成a async void然后将其传递给Func<Task>.的构造函数.什么是确保编译为Func<Task>?的理想方法?
小智 29
由于
Task.Run既有的签名Task.Run(Func<Task>)和Task.Run(Action),是什么类型编译异步匿名函数?一个async void还是一个Func<Task>?我的直觉是它会编译成async void纯粹因为它是非泛型类型,但C#编译器可能很聪明并且给出了Func<Task>类型偏好.
即使没有async,一般规则是具有返回类型的委托比没有返回类型的委托更好地匹配.另一个例子是:
static void Foo(Action a) { }
static void Foo(Func<int> f) { }
static void Bar()
{
Foo(() => { throw new Exception(); });
}
Run Code Online (Sandbox Code Playgroud)
这是明确的,并称为第二次重载Foo.
另外,有没有办法明确声明我希望使用哪个重载?
明确这一点的一个好方法是指定参数名称.Action和Func<Task>重载的参数名称是不同的.
Task.Run(action: async () => {
await Task.Delay(1000);
});
Task.Run(function: async () => {
await Task.Delay(1000);
});
Run Code Online (Sandbox Code Playgroud)
Sri*_*vel 27
我刚检查它Task.Run(Func<Task>)默认编译进去,我对此没有很好的解释.
这是IL的相关部分
IL_0001: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0006: brtrue.s IL_001B
IL_0008: ldnull
IL_0009: ldftn UserQuery.<Main>b__0
IL_000F: newobj System.Func<System.Threading.Tasks.Task>..ctor//<--Note here
IL_0014: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0019: br.s IL_001B
IL_001B: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0020: call System.Threading.Tasks.Task.Run
Run Code Online (Sandbox Code Playgroud)
您可以使用visual studio类型推断轻松地检查这一点,如果您只是将鼠标放在方法上,它将显示它将被编译的方法,或者只需单击方法按下F12您可以看到元数据,它将告诉您推断的类型是什么通过编译器.
另外,有没有办法明确声明我希望使用哪个重载?是,明确指定委托.
Task.Run(new Action(async () =>
{
await Task.Delay(1000);
}));
Task.Run(new Func<Task>(async () =>
{
await Task.Delay(1000);
}));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
53769 次 |
| 最近记录: |