2012-08-13 18 views
10

Se si dispone di una lambda come () => { throw new Exception(); }, non è chiaro se ha un tipo di ritorno o meno. Per questo motivo, può essere (implicitamente) convertito in entrambi Action e Func<object> (o qualsiasi altro Func<T>). Questo perché, secondo il punto 6.5 anonimi conversioni funzione del C# 4 spec:Conversioni lambda con tipo di ritorno non chiaro e risoluzione di sovraccarico

[A] delegato tipo D è compatibile con una funzione anonima F condizione:

  • ...

  • Se D ha un tipo di ritorno void e il corpo di F è un blocco di istruzioni, quando il [...] corpo di F è un blocco di istruzioni valido in cui nessuna istruzione return specifica un'espressione.

  • Se D ha un tipo di ritorno non nullo e il corpo di F è un blocco di istruzioni, quando [...] il corpo di F è un blocco di istruzioni valido con un punto finale non raggiungibile in cui ogni return specifica istruzione un'espressione che è implicitamente convertibile nel tipo restituito di D.

Ma se devo due overload di un metodo, in cui si ha un parametro di tipo Action e l'altra Func<object>, e lo passo lambda dall'alto, viene usato in sovraccarico Func<object>. Perché? Quale parte della specifica dice che Func<object> è meglio di Action in questo caso?

Ho visto §7.5.3.2 Membro di funzione migliore, ma questo non lo spiega.

+0

E se, invece di sintassi lambda, si utilizza la notazione 'delegate {throw new Exception(); } 'dove si omette la lista dei parametri tra parentesi'() ', quella funzione anonima potrebbe corrispondere a ** qualsiasi ** firma delegata che immagino, includendo anche per es. 'EventHandler' e' Azione '. –

+0

@JeppeStigNielsen Sì. In tal caso, non c'è davvero alcuna regola per disambigarli come parametri del metodo, in modo da ottenere un errore di compilazione. – svick

risposta

11

Avrei dovuto guardare una sezione in basso: § 7.5.3.3 Meglio conversione dall'espressione spiega che:

Data una conversione implicita C1 che converte da un'espressione E a un tipo T1, e una conversione implicita C2 che converte da un'espressione E a un tipo T2, C1 è una conversione migliore rispetto C2 se almeno una delle seguenti vale:

  • ...

  • E è una funzione anonima, T1 è o un tipo delegato D1 o un tipo di albero di espressione Expression<D1>, T2 è o un tipo delegato D2 o un albero di espressione tipo Expression<D2> e uno dei seguenti tiene:

    • ...

    • D1 e D2 hanno elenchi di parametri identici, e una delle seguenti stive:

      • ...

      • D1 ha un tipo di ritorno Y, e D2 è vuoto tornando

+1

Hai postato questa risposta nello stesso secondo in cui hai posto la domanda? –

+6

Sì, mentre stavo scrivendo la domanda, ho notato la risposta nelle specifiche. Quindi non volevo sprecare il tempo di nessuno a ricercarlo. Ma allo stesso tempo, ho pensato che potesse essere utile per qualcun altro. – svick

+1

Questa risposta spiega come il comportamento osservato si adatta alle specifiche, ma non (e non può) spiegare perché le specifiche sono state scritte in quel modo in primo luogo. Fortunatamente, [ora abbiamo una parola] (http://stackoverflow.com/questions/24316189/peculiar-overload-resolution-with-while-true/24316474?noredirect=1#comment37681268_24316474) dalla persona che ha implementato la funzione nel compilatore che spiega anche questo! – Jon

Problemi correlati