2015-08-27 14 views
6

nella mia richiesta, ho il codice simile al seguente:ambiguo C# chiamata di metodo con i delegati

class Program 
    { 
     static void Main(string[] args) 
     { 
      Method(uri => Task.FromResult(uri)); 
     } 

     static void Method(Func<Uri, Uri> transformer) 
     { 
      throw new NotImplementedException(); 
     } 

     static void Method(Func<Uri, Task<Uri>> transformer) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Come previsto, l'esecuzione di questo codice chiama il secondo sovraccarico del 'Metodo', quella in attesa di un funzione di delegato che restituisce un compito. Tuttavia, se cambio il codice per evitare di utilizzare il metodo anonimo in Main:

class Program 
    { 
     static void Main(string[] args) 
     { 
      Method(Method2); 
     } 

     static Task<Uri> Method2(Uri uri) 
     { 
      return Task.FromResult(uri); 
     } 

     static void Method(Func<Uri, Uri> transformer) 
     { 
      throw new NotImplementedException(); 
     } 

     static void Method(Func<Uri, Task<Uri>> transformer) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Il compilatore C# ora si lamenta che la mia chiamata a 'Metodo' è ambiguo. Cosa mi manca?

+1

non si passa un Uri a Method2. –

+0

@ SamAxe lui non intende. Sta provando a convertire un * metodo group * ('Method2') in un delegato (' Func > ') – dcastro

+0

Probabilmente perché' TResult' in 'Func ' è covariante. – haim770

risposta

1

La risposta lunga è https://stackoverflow.com/a/2058854/1223597 (come sottolineato da richzilla).

La risposta breve è che il team del compilatore C# ha scelto di eseguire conversioni di gruppo metodo (come Method(Method2)) per ignorare il tipo restituito (qui di Method2). Questo dà loro la flessibilità nel modo in cui vengono analizzati gli alberi Expression. Sfortunatamente ciò significa che il compilatore non può scegliere implicitamente tra le tue 2 firme Method.

Quando si esegue una conversione lambda, (Method(uri => Task.FromResult(uri))), il team del compilatore non deve preoccuparsi del parsing dell'albero delle espressioni, pertanto i tipi di ritorno sono .