2015-01-06 11 views
24

Ho letto che C# lambda può essere inserito implicitamente convertiti in azione o Func, ma lambda non può essere eseguito direttamente Define a lambda function and execute it immediately Ad esempio:Qual è il vero tipo di lambda in C#?

int n = (()=>5)(); //doesn't work 
int n = ((Func<int>)(()=>5))(); //works 

Allora, qual è il tipo effettivo di lambda e il motivo per cui non può essere chiamato direttamente? È perché il sistema di tipo C# è "più debole" di quello di Haskell o di Scala?

+2

Tipo anonimo ??. –

+2

La risposta nella domanda collegata è valida per la tua domanda. Il compilatore C# ha bisogno di conoscere il contesto, che è o un compito o un casting. Nel primo esempio non si utilizza né – Leri

+0

Il sistema di tipi non è correlato a questo. 'Dim n = Function() 5' funziona bene in VB.NET, ed è simile in F #, e hanno lo stesso sistema di tipo sottostante. Questo è solo un problema con C#. –

risposta

26

Un'espressione lambda non ha un tipo. Non può, poiché qualsiasi tipo nel mondo .NET che potrebbe avere, potrebbe anche codificare il tipo dei parametri e del risultato di lambda. Consideriamo ora:

x => x + 1 

Che tipo potrebbe x avere? Di che tipo sarà il risultato? Non esiste una risposta singola e l'espressione lambda può essere effettivamente convertita in Func<int, int>, Func<double, double> e molti altri tipi di delegati con parametri diversi. Dare un'espressione lambda di tipo non consentirebbe tali espressioni. C# voleva consentire tali espressioni, quindi è stato progettato per non dare alcun tipo a espressioni del genere.

+1

ben spiegato, se un esempio di codice è dato, sono instersted –

+2

non sono sicuro che tipo di codice di esempio hai in mente, tutto quello che posso pensare di aggiungere sono esempi di tipi di delegati a cui è possibile convertire l'espressione, che ora ho incluso nella risposta. – hvd

+0

Ha senso. Ho appena provato questo in F # e Haskell. In F # in funziona solo per "int" - la ragione è che F # non usa conversioni implicite. Nel caso di C# - il compilatore non può davvero "conoscere" il tipo, quindi hai ragione. –

9

Questo perché () => 5 può essere compatibile con vari tipi di delegati (ad esempio potresti avere un numero personalizzato delegate che non richiede nulla e restituisce int). E per creare un delegate, il compilatore deve conoscere il tipo esatto. Non può semplicemente scegliere un tipo casuale che si adatta alle tue esigenze. Ecco perché, a meno che non lo si lanci su un tipo di delegato effettivo, non è possibile farlo Invoke.

In casi come un metodo in cui si aspetta un delegate, che la conversione è implicitamente fatta dal compilatore:

void Foo(Func<int> func) { } 

Foo(() => 5); 

Ed è anche importante sapere che delegates sono in realtà le classi dietro le quinte. Ogni volta che crei un'istanza delegate, il compilatore crea un'istanza di tale class. Quindi in entrambi i casi devi specificare un tipo in modo che il compilatore sappia quale tipo usare.

+0

quando mettiamo ''() => '' in '' Select() '' o '' Where() '' cosa significa? per favore spiegami –

+0

@EhsanSajjad stavo solo aggiungendo quello alla risposta :) –

+0

ho bisogno di chiarimenti per me stesso perché non sono chiaro .. :) –

Problemi correlati