Sto scrivendo una semplice applicazione di console C# che utilizza Asynchronous Tasks ed Entity Framework (con l'intento di eseguirlo su Linux (RHEL) con Mono, ma questa è un'altra sfida). Si noti che sto prendendo come destinazione .NET 4.0, quindi sto utilizzando .ContinueWith()
anziché await
.Invocazione ambigua su Generic Continue con il
Questo, più il modello EF DB di un database Northwind, è la totalità della richiesta:
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());
}
}
}
Il problema è che sto ottenendo il seguente errore al .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
Per me, l'invocazione non dovrebbe essere ambigua, il compilatore dovrebbe preferire l'attività generica sull'Attività non generica, specialmente perché è l'output di GetCustomerNamesAsync()
. Tuttavia, come sviluppatore VB.NET, probabilmente mi affido a Option Infer
in questa situazione.
Come farei esplicitamente a lasciare che il compilatore sappia quale invocazione voglio che usi in C#?
Mi hai portato alla soluzione giusta. Dichiarare esplicitamente '.ContinueWith ((Task t) => {...})' poi ha smascherato il problema successivo, che stavo chiamando 'Console.WriteLine (t.Exception.Flatten.ToString)' invece di 'Console.WriteLine (t.Exception.Flatten(). ToString()) '. Dopo aver corretto questo, sono stato in grado di rimuovere la dichiarazione del parametro lambda esplicito e il compilatore era felice. –
MCattle
@MCattle Interessante che le parentesi mancanti potrebbero rendere il compilatore incapace di decidere tra i due overload. Ero un po 'sospettoso della mia risposta, perché non ricordavo di dover dare esplicitamente il tipo di input lambda all'infinito numero di volte in cui ho usato 'ContinueWith'. Non so spiegare perché le parentesi mancanti farebbero la differenza. –
Ha senso per me, perché il sovraccarico è dedotto dall'utilizzo e se c'è un errore di sintassi nell'utilizzo, non è possibile dedurre il sovraccarico corretto. – MCattle