2012-06-04 16 views
9

Perché quanto segue non riescono a dedurre R:inferenza di tipo non riesce misteriosamente

static R Foo<R>(Func<Action<R>, R> call) { ... } 

Mentre più o meno lo 'stesso', funziona:

static R Foo<R>(Func<Action, R> call) { ... } 

utilizzo:

var i = Foo(ec => -1); 

Ways il primo campione "deve" essere chiamato per compilare:

var i = Foo<int>(ec => -1); 

- o -

var i = Foo((Action<int> ec) => -1); 

Pensieri: Come si può vedere nel secondo frammento di, R è già determinato dal tipo di ritorno del 'lambda'. Perché lo stesso non può valere per il primo? Anche con l'utilizzo di ec (che dovrebbe essere un altro suggerimento del compilatore), non riesce a dedurre.

+0

Quindi, nell'esempio, 'ec' è convertibile in un delegato che prende un' int' e restituisce 'void'? –

+0

Nel primo esempio, sì. – leppie

+0

Le regole di inferenza del tipo in C# sono fatte per coprire i casi di base. Ci sono alcuni rari casi in cui le regole (intenzionalmente) non "prendono". – usr

risposta

4

Penso che il problema non è che il compilatore, se non riuscire a dedurre R per la funzione CallWithEscapeContinuation, è che non riesce a dedurre un tipo per il lambda:

ec => 
{ 
    Enumerable.Range(0, 100).Select(x => 
    { 
       // Called here, the compiler has no idea what signature to expect for `ec` 
       // Could be Action<Int>, could be Action<Decimal> (for example). 
    if (x == 40) ec(x); 
    return x; 
    }).ToList(); 
    return -1; 
} 

Considerando che quando si fornisce il int suggerimento, può dedurre che tipo è la lambda e la firma di CallWithEscapeContinuation.

Quando hai appena Action (al contrario di Action<R>) quanto sopra è irrilevante perché non ci sono parametri di tipo che influenzano le possibili firme della lambda.

+0

Intervalli restituiti 'IEnumerable ', perché 'x' deve essere nient'altro che un' int'? – leppie

+0

Se si commenta tutto e si torna semplicemente -1, non si deduce neanche il tipo di ritorno. – Slugart

+0

Anche in questo caso fallirà: 'var index = CallWithEscapeContinuation (ec => {ec (1); return -1;});' – leppie

Problemi correlati