2013-02-12 12 views
9

Quando S e T sono differenti, questo funziona:T di Func <S, T> viene dedotto dall'output dell'espressione lambda solo quando S e T sono diversi?

public static void Fun<S, T>(Func<S, T> func) 
{ 

} 

Fun((string s) => true); //compiles, T is inferred from return type. 

Ma,

public static void Fun<T>(Func<T, T> func) 
{ 

} 

Fun(t => true); //can't infer type. 

Nel primo esempio, dal momento T viene dedotto dal tipo di ritorno di espressione lambda, non può T nel anche il secondo esempio può essere dedotto? Suppongo che lo faccia, ma perché non è noto il primo T, quando è noto il secondo T di Func<T, T>, dopo tutto T == T giusto? Oppure esiste un ordine per i tipi dedotti in caso di Func s?

+0

'S' non è dedotto nel primo esempio, quindi non è una questione di differenza. Sono d'accordo che sembra che l'inferenza dovrebbe funzionare nel secondo esempio. – Jodrell

+0

@Jodrell sure 'S' non è dedotto, non può, ma' T' è, non è vero .. – nawfal

risposta

13

Non ha assolutamente niente a che fare con S e T. Ha a che fare con te fornendo il tipo di parametro formale nel primo caso e non fornendolo nel secondo caso.

Inferenza tipo metodo non tenta di inferire il tipo di restituzione di un delegato da una lambda fino a quando i tipi di parametro formale del delegato sono noti.

Nel secondo caso non hai fornito al compilatore nulla con cui dedurre il parametro formale tipo T, e quindi il corpo della lambda non verrà nemmeno analizzato.

Cosa si intende per "tipo di parametro formale"?

Un parametro formale è una variabile che assume il valore di un argomento passato a un metodo, un indicizzatore, un costruttore, un lambda o un metodo anonimo. (Oppure, nel caso dei parametri formali out e ref, diventa un alias di una variabile fornita dal chiamante.) I parametri formali sono variabili e quindi hanno tipi .

Il delegato delegate R Func<A, R>(A a); ha il parametro formale a con tipo A. Lo si costruisce con i parametri del tipo metodo per rendere Func<S, T>, quindi il tipo di parametro formale del delegato è ora S. Il compito di tipo inferenza è quello di inferire quei tipi S e T.

Nel primo esempio si dispone di una lambda con parametro formale s di tipo string. Quindi, per ragioni di inferenza, poiché questo argomento lambda corrisponde al parametro formale func del metodo Fun e il tipo di parametro formale di func è Func<S, T>, il tipo di parametro formale s deve corrispondere a S. Poiché è stato assegnato un tipo di parametro formale per s, S viene considerato come string.

Una volta effettuata l'inferenza, è possibile dedurre T analizzando il corpo della lambda.

Nel secondo caso, non è stato specificato alcun tipo di parametro formale per t. Poiché non c'è nient'altro da cui dedurre il tipo di t, l'inferenza si interrompe e abbandona l'analisi di questa lambda prima di guardare il corpo.

Accade solo che nel tuo caso il corpo possa essere analizzato indipendentemente dal tipo di parametro formale della lambda. Questo è un caso raro e l'algoritmo di inferenza del tipo non è stato scritto per trarne vantaggio.

Se questo è il tipo di inferenza di tipo desiderata, prendere in considerazione l'utilizzo di F # anziché di C#. Ha un algoritmo di inferenza di tipo molto più avanzato, basato sull'algoritmo Hindley-Milner.

+0

Che cos'è il "tipo di parametro formale"? Ho fornito solo 'S' nel primo caso, vero? Quindi qui 'S' è il parametro formale? Quindi intendi tipi di input giusti? – nawfal

+1

@nawfal, ho capito questo dalla risposta, 'Func '. – Jodrell

+1

aggiornerò la risposta. È troppo complicato da spiegare in un commento. –

5

I parametri generici per lambda e altre funzioni sono determinati dai relativi tipi di parametri, non dal tipo di ritorno. E 'esattamente la stessa ragione per cui non si può fare questo:

T Foo<T>() { return default(T); } 

string x = Foo(); // error 

Per l'espressione t => true, abbiamo chiaramente non sappiamo cosa t potrebbe essere in modo che il compilatore non può fare altre decisioni basate su questo da solo.

+0

Ma come si deduce 'T' nel primo esempio? Il tipo di reso è dedotto giusto? – nawfal

Problemi correlati