【问题标题】:Return types within a Task running an async anonymous function?运行异步匿名函数的任务中的返回类型?
【发布时间】:2016-08-09 02:45:53
【问题描述】:

我有一个返回Task<String> 的函数,要构造这个Task,我必须使用匿名async 函数,因为我必须在await 中多次调用Task。我发现我可以返回 "",但如果我尝试返回 null 则会出现错误(Visual Studio 消息)

转换为 void 返回委托的匿名函数无法返回值

转换为“任务”返回委托的异步 lambda 表达式无法返回值。您是否打算返回“任务”?

显示相同问题的函数

public virtual Task<String> FooBar()
{
    return Task<String>.Run(async () =>
    {
        await Task.Delay(1500);
        return ""; // OK
        //return null; // Error 
    });
}

这里发生了什么?

如果我想返回一个空值,return await Task.FromResult&lt;String&gt;(null); 会更合适吗?

【问题讨论】:

  • 你为什么首先使用Task.Run?你没有 CPU 绑定的工作,你有异步工作;只需完全删除该调用,因为它在这里什么也没做。
  • 值得注意的是Task&lt;String&gt;.RunTask.Run 完全相同,因为它是基类上的静态方法。编译器仍然需要从提供给Run 的委托中推断返回类型(仅使用null 无法继续)。
  • @CharlesMager 说得通,并解决了另一个“问题”。 Visual Studio 使&lt;String&gt; 部分略微变灰,指出它不是必需的。我知道它以某种方式推断类型,但现在我明白它是如何做到的了。
  • @Servy 方法 FooBar 旨在创建一些任务来执行可能会受到 CPU 限制的任务。在某些情况下,“真正的工作”已经完成,但在其他情况下,它是异步的。当我写下我从错误消息中假设的问题时,它必须专门使用 async 函数,尽管现在我发现情况并非如此。

标签: c#


【解决方案1】:

编译器不知道null 是字符串的null,因此不能自动选择正确的类型Func&lt;Task&lt;string&gt;&gt;。改为执行以下操作以告诉编译器 null 用于字符串。

return (string)null;

另外,正如 cmets 中提到的,Task.Run&lt;TResult&gt;(Func&lt;Task&lt;TResult&gt;&gt; function) 是一个静态方法,所以当您执行Task&lt;String&gt;.Run(... 时,您仍然调用相同的静态方法Task.Run,没有额外信息。您需要做的是调用它并将类型传递给Run 部分,强制返回类型为string,而不是让编译器尝试找出返回类型应该是什么。

public virtual Task<String> FooBar()
{
    return Task.Run<String>(async () =>
    {
        await Task.Delay(1500);
        return null; // Does not error 
    });
}

【讨论】:

  • 打我!或者,您可以使用Task.Run&lt;String&gt;
  • 仅供参考,您可以使用Task.Run&lt;string&gt;(...) 代替Task&lt;string&gt;.Run(...)
  • default(string)
  • 有趣的是,如果这是正确的术语,我从未见过“casted null”。
  • @KDecker 我有机会测试它,如果你对Test(null); 执行void Test(params Foo[] foos),传入的变量将等同于foos = null;。如果你这样做Test((Foo)null);,传入的变量将等同于foos = new Foo[] { null };。我还更新了我的答案,解释了 Stephen Cleary 在他的评论中所做的事情。
猜你喜欢
  • 1970-01-01
  • 2014-05-29
  • 2019-05-04
  • 2011-05-20
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多