7

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

这与 Northwind 数据库的 EF DB 模型一起构成了整个应用程序:

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()

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# 中使用哪个调用?

4

1 回答 1

13

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

.ContinueWith((Task<string[]> t) => { ... })

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

Task<TResult>.ContinueWith(Action<Task<TResult>> action)
Task<TResult>.ContinueWith(Action<Task> action) //inherited from `Task`

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


如果编译器可以采用Action<Task<TResult>> action. 也许其他人对如何获得这种行为有想法?


为后人...

在评论中,您会看到 MCattle 发现他只是遇到了这个问题,因为编译器的一些奇怪之处与他的 lambda 中的方法调用中缺少括号有关。通常,Task<TResult>在将 lambda 传递给ContinueWith.

于 2013-05-22T17:21:41.810 回答