首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型ContinueWith上的二义性调用

泛型ContinueWith上的二义性调用
EN

Stack Overflow用户
提问于 2013-05-23 01:17:17
回答 1查看 3.4K关注 0票数 7

我正在编写一个简单的C#控制台应用程序,它使用异步任务和实体框架(意图使用Mono在Linux (RHEL)上运行它,但这是一个完全不同的挑战)。请注意,我的目标是.NET 4.0,所以我使用的是.ContinueWith()而不是await

这一点,加上Northwind数据库的EF DB模型,就是整个应用程序:

代码语言:javascript
复制
using System;
using System.Linq;
using System.Threading.Tasks;

namespace MonoEF
{
    class Program
    {
        private static Model.NorthwindEntities _db = new Model.NorthwindEntities();

        static void Main(string[] args)
        {
            try
            {
                GetCustomerNamesAsync().ContinueWith(t => {
                    if (t.IsFaulted) Console.WriteLine(t.Exception.Flatten.ToString);
                        else if (t.IsCompleted) foreach (string result in t.Result) Console.WriteLine(result);
                    });

                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        private static Task<string[]> GetCustomerNamesAsync()
        {
            return Task.Factory.StartNew(() => (from c in _db.Customers select c.ContactName).Distinct().ToArray());
        } 

    }
}

问题是我在.ContinueWith()中得到了以下错误

代码语言:javascript
复制
Ambiguous Invocation:
  System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task<string[]>>) (in class Task<string[]>)
  System.Threading.Tasks.Task.ContinueWith(System.Action<System.Threading.Tasks.Task>) (in class Task)
match

对我来说,调用不应该是模棱两可的,编译器应该更喜欢泛型任务而不是非泛型任务,特别是因为它是GetCustomerNamesAsync()的输出。但是,作为一名VB.NET开发人员,在这种情况下我可能会依赖Option Infer

我该如何显式地让编译器知道我希望它在C#中使用哪个调用呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-23 01:21:42

尝试显式指定lambda参数类型,如下所示:

代码语言:javascript
复制
.ContinueWith((Task<string[]> t) => { ... })

您调用它的方式的问题是Task<TResult>Task (它的基类)都有一个看起来几乎相同的ContinueWith方法:

代码语言:javascript
复制
Task<TResult>.ContinueWith(Action<Task<TResult>> action)
Task<TResult>.ContinueWith(Action<Task> action) //inherited from `Task`

如果不指定action的输入类型,编译器就无法确定您想要哪个重载。显式地提供action lambda的输入参数类型可以解决这种歧义。

如果编译器可以假定采用Action<Task<TResult>> action的版本,那就太好了。也许其他人对如何获得这样的行为有想法?

为了子孙后代。

在注释中,您将看到MCattle发现他之所以会遇到这个问题,是因为在他的lambda中的方法调用中缺少圆括号,这与编译器的一些奇怪之处有关。通常,在将lambda传递给ContinueWith时,不需要显式指定Task<TResult>类型。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16697897

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档