2015-01-06 4 views
24

ich gelesen, dass # lambdas C können imlicitly zum Handeln oder Func umgewandelt werden, aber Lambda kann nicht direkt Define a lambda function and execute it immediately Zum Beispiel ausgeführt werden:Wie ist der tatsächliche Lambda-Typ in C#?

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

Also, was die tatsächliche Art von Lambda ist und warum sie genannt werden, können nicht direkt? Liegt es daran, dass das C# -Typsystem "schwächer" ist als Haskell oder Scala?

+2

Anonyme Art ??. –

+2

Die Antwort in der verknüpften Frage gilt für Ihre Frage. Der C# -Compiler muss den Kontext kennen, der entweder Zuweisung oder Casting ist. Im ersten Beispiel tun Sie weder – Leri

+0

Das Typsystem ist nicht damit verbunden. 'Dim n = Function() 5 'funktioniert in VB.NET gut und in F # ist es ähnlich, und sie haben das gleiche zugrundeliegende Typsystem. Dies ist nur ein Problem mit C#. –

Antwort

26

Ein Lambda-Ausdruck hat keinen Typ. Es kann nicht, weil jeder Typ in der .NET-Welt, die es haben könnte, auch den Typ der Parameter und das Ergebnis des Lambdas hartcodieren würde. Betrachten wir nun:

x => x + 1 

Welche Art könnte x haben? Welcher Art wird das Ergebnis sein? Es gibt keine einzige Antwort und der Lambda-Ausdruck kann tatsächlich in Func<int, int>, Func<double, double> und viele andere Delegattypen mit unterschiedlichen Parametern konvertiert werden. Würde man einem Lambda-Ausdruck einen Typ geben, würde man solche Ausdrücke nicht zulassen. C# wollte solche Ausdrücke zulassen, so wurde entworfen, um solchen Ausdrücken keinen Typ zu geben.

+1

gut erklärt, wenn ein Codebeispiel gegeben werden, bin ich intersted –

+2

Ich bin mir nicht sicher Was für ein Codebeispiel Sie im Sinn haben, alles was ich hinzufügen kann, sind Beispiele für Delegattypen, in die der Ausdruck konvertiert werden könnte, die ich jetzt in die Antwort aufgenommen habe. – hvd

+0

Es macht Sinn. Ich habe das gerade in F # und Haskell getestet. In F # funktioniert nur für "int" - der Grund ist, dass F # keine impliziten Konvertierungen verwendet. Im Falle von C# - Compiler kann wirklich nicht den Typ "wissen", also hast du recht. –

9

Dies liegt daran, () => 5 kann mit verschiedenen Delegate-Typen kompatibel sein (z. B. haben Sie möglicherweise eine benutzerdefinierte delegate, die nichts dauert und int zurückgibt). Und um einen delegate zu erstellen, muss der Compiler den genauen Typ kennen. Es kann nicht einfach einen zufälligen Typ auswählen, der Ihren Anforderungen entspricht. Aus diesem Grund können Sie nicht Invoke es, es sei denn, Sie werfen es auf einen tatsächlichen Delegate-Typ.

void Foo(Func<int> func) { } 

Foo(() => 5); 

Und es ist auch wichtig zu wissen, dass delegates eigentlich Klassen hinter den Kulissen sind:

In solchen Fällen, wo ein Verfahren zur Herstellung eines delegate erwartet wird, dass die Konvertierung implizit vom Compiler getan. Und jedes Mal, wenn Sie eine delegate Instanz erstellen, erstellt der Compiler eine Instanz dieser class. In beiden Fällen müssen Sie einen Typ angeben, damit der Compiler den zu verwendenden Typ kennt.

+0

wenn wir ''() => '' in '' Select() '' oder '' Where() '' was es bedeutet? Bitte erläutern Sie –

+0

@EhsanSajjad Ich habe nur hinzugefügt, dass die Antwort :) –

+0

Ich brauche Klärung für mich, weil ich nicht klar bin .. :) –

Verwandte Themen