Piszę prostą aplikację konsoli C#, która używa Asynchronous Tasks i Entity Framework (z zamiarem uruchomienia jej pod Linuksem (RHEL) z Mono, ale to jest zupełnie inne wyzwanie). Zwróć uwagę, że jestem kierowany na .NET 4.0, więc używam .ContinueWith()
zamiast await
.Niejednoznaczna inwokacja na ogólnej kontynuacji
To, plus model EF DB z bazy danych Northwind, to całość wniosku:
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());
}
}
}
Problemem jest Dostaję następujący błąd na .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
Dla mnie, inwokacja nie powinna być niejednoznaczna, kompilator powinien preferować ogólne zadanie nad nietypowym zadaniem, szczególnie, że jest to wyjście z GetCustomerNamesAsync()
. Jednak jako programista VB.NET, prawdopodobnie polegam na Option Infer
w tej sytuacji.
W jaki sposób chciałbym wyraźnie poinformować kompilator, jakie wywołanie chcę użyć w C#?
Poprowadziłeś mnie do właściwego rozwiązania. Jawne deklarowanie '.ContinueWith ((Task t) => {...})' następnie odtajniło następny problem, który wywoływałam 'Console.WriteLine (t.Exception.Flatten.ToString)' zamiast 'Console.WriteLine (t.Exception.Flatten(). ToString()) '. Po naprawieniu tego mogłem usunąć jawną deklarację parametru lambda, a kompilator był zadowolony. –
MCattle
@MCattle Ciekawe, że brakujące nawiasy sprawiłyby, że kompilator nie byłby w stanie zdecydować między dwoma przeciążeniami. Byłem trochę podejrzliwy wobec mojej własnej odpowiedzi, ponieważ nigdy nie pamiętałem, aby musiałem jawnie podawać dane wejściowe lambda niezliczoną ilość razy, kiedy sam użyłem 'ContinueWith'. Nie potrafię wyjaśnić, dlaczego brakujący nawias sprawiłby różnicę. –
Ma sens dla mnie, ponieważ przeciążenie jest wnioskowane na podstawie użycia, a jeśli wystąpił błąd składni w użyciu, to nie można wywnioskować właściwego przeciążenia. – MCattle