16 Stimmen

C# Action-Lambda-Beschränkung

Warum lässt sich dieser Lambda-Ausdruck nicht kompilieren?

Action a = () => throw new InvalidOperationException();

Vermutungen sind in Ordnung, aber ich würde mich über Verweise auf die C#-Sprachspezifikation oder andere Unterlagen freuen.

Und ja, ich weiß, dass das Folgende gültig ist und kompiliert werden kann:

Action a = () => { throw new InvalidOperationException(); };

Der Kontext, in dem ich so etwas verwenden würde, wird unter dieser Blogbeitrag .

19voto

Jon Skeet Punkte 1325502

Hm. Ich habe eine Antwort, aber sie ist nicht gut.

Ich glaube nicht, dass es einen "Wurf" gibt. Ausdruck . Es gibt einen Wurf Anweisung , aber nicht nur ein Ausdruck. Vergleichen Sie dies mit "Console.WriteLine()", das ein Ausdruck für einen Methodenaufruf mit dem Typ "void" ist.

Parallel dazu können Sie keine switch-Anweisung oder eine if-Anweisung usw. als eigenständigen Körper eines Lambda verwenden. Sie können nur einen Ausdruck oder einen Block haben (Abschnitt 7.14).

Ist das hilfreich?

15voto

leppie Punkte 111830

Hier ist meine Meinung dazu:

throw ist eine Aussage, kein Ausdruck.

Und die Referenz:

12.3.3.11 Wurfanweisungen

Für eine Anweisung der Form stmt

throw expr;

den definitiven Zuweisungsstatus von v am Anfang von expr ist derselbe wie der definitive Zuweisungszustand von v am Anfang von stmt.

Um das Wesentliche zu erklären, sollte man vielleicht darüber nachdenken, was ein Ausdruck innerhalb des C#-Lambda-Konstrukts impliziert. Es ist einfach syntaktischer Zucker für:

delegate () { return XXX; }

donde XXX ist ein Ausdruck

1voto

Nic Wise Punkte 7791

Alle Referenzen, die ich finden kann, finden Sie hier:

http://msdn.microsoft.com/en-us/library/ms364047(VS.80).aspx#cs3spec_topic4

zeigen, dass Sie zwei Möglichkeiten haben:

Action a = () => { throw new InvalidOperationException(); };

o

Action a = () => throw new InvalidOperationException()

Beachten Sie das fehlende ; am Ende. Ja, das ergibt für mich auch keinen Sinn. Die Beispiele, die sie in der Spezifikation geben, sind:

x => x + 1                     // Implicitly typed, expression body
x => { return x + 1; }         // Implicitly typed, statement body
(int x) => x + 1               // Explicitly typed, expression body
(int x) => { return x + 1; }   // Explicitly typed, statement body
(x, y) => x * y               // Multiple parameters
() => Console.WriteLine()      // No parameters

Keine Ahnung, wie viel Hilfe das ist - ich kann nicht sagen, in welchem Kontext Sie es verwenden, und nicht ein ; am Ende macht keinen Sinn in C #

der Unterschied kann darin bestehen, dass es sich um einen Ausdrucksrumpf und nicht um eine Anweisung handelt, wenn das {} nicht vorhanden ist. Das bedeutet, dass Ihr Wurf dort nicht gültig ist, da es sich um eine Anweisung und nicht um einen Ausdruck handelt!

1voto

Sie können nicht zurückkehren oder werfen aus einem un-scoped Lambda.

Betrachten Sie es so... Wenn Sie kein {} angeben, bestimmt der Compiler, was Ihr impliziter Rückgabewert ist. Wenn Sie throw innerhalb des Lambdas, gibt es keinen Rückgabewert. Sie geben nicht einmal void . Warum das Compiler-Team diese Situation nicht in den Griff bekommen hat, weiß ich nicht.

0voto

yfeldblum Punkte 64211

Keine große Überraschung. Lambda-Ausdrücke sind ein Aspekt von funktionell Programmierung. Ausnahmen sind ein Aspekt der Verfahren Programmierung. Das C#-Geflecht zwischen den beiden Programmierstilen ist nicht perfekt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X