Ambiguous call on shared continuation with

I am writing a simple console application in C # that uses Asynchronous Tasks and Entity Framework (with the intention of running it under Linux (RHEL) using Mono, but this is another problem). Note that I am targeting .NET 4.0, so I use .ContinueWith() instead of await .

This, plus the Northwind database EF DB model, is a complete application:

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

The problem is that I get the following error in .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 

For me, the call should not be ambiguous, the compiler should prefer a general task for a non-general task, especially since it outputs GetCustomerNamesAsync() . However, as a VB.NET developer, I probably rely on Option Infer in this situation.

How can I explicitly tell the compiler which call I want to use in C #?

+6
source share
1 answer

Try explicitly specifying the type of lambda parameter, for example:

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

This problem with how you called it is that Task<TResult> and Task (its base class) have a ContinueWith method that looks almost the same:

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

Without specifying the input type of the action compiler cannot determine what kind of overload you want. Explicitly providing the parameter type action lambda input resoles this ambiguity.


Of course, it would be nice if the compiler could take a version that takes Action<Task<TResult>> action . Maybe someone has an idea how to get this behavior?


For posterity ...

In the comments, you will see that MCattle found that it encountered this problem only due to some compiler oddness associated with missing brackets when calling a method inside its lambda. In general, you don’t need to explicitly specify the type of Task<TResult> when passing lambda to ContinueWith .

+10
source

Source: https://habr.com/ru/post/945611/


All Articles