Es ist möglich, eine Lambda-Funktion zu deklarieren und sofort aufzurufen:
Func<int, int> lambda = (input) => { return 1; };
int output = lambda(0);
Ich frage mich, ob es möglich ist, dies in einer Zeile zu tun, z
int output = (input) => { return 1; }(0);
Dies gibt einen Compilerfehler "Methodenname erwartet". Casting to Func<int, int>
funktioniert auch nicht:
int output = (Func<int, int>)((input) => { return 1; })(0);
gibt den gleichen Fehler aus, und aus den unten genannten Gründen möchte ich vermeiden, den Eingabeargumenttyp (den ersten int
) explizit angeben zu müssen .
Sie fragen sich wahrscheinlich, warum ich das tun möchte, anstatt nur den Code direkt einzubetten, z int output = 1;
. Der Grund ist folgender: Ich habe eine Referenz für einen SOAP-Webservice mit generiert svcutil
, der aufgrund der verschachtelten Elemente extrem lange Klassennamen generiert, die ich vermeiden möchte, eingeben zu müssen. Also statt
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = CreateAddress(sh.ReceiverAddress_Shipment);
}).ToArray()
};
und eine separate CreateAddress(GetOrderResultOrderShipment_OrderShipmentShipment_Address address)
Methode (echte Namen sind noch länger und ich habe nur sehr begrenzte Kontrolle über das Formular), möchte ich schreiben
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = sh.ReceiverAddress_Shipment == null ? null : () => {
var a = sh.ReceiverAddress_Shipment.Address;
return new Address {
Street = a.Street
...
};
}()
}).ToArray()
};
Ich weiß, ich könnte schreiben
Address = sh.ReceiverAddress_Shipment == null ? null : new Address {
Street = sh.ReceiverAddress_Shipment.Address.Street,
...
}
Aber selbst das (der sh.ReceiverAddress_Shipment.Address
Teil) wiederholt sich sehr, wenn es viele Felder gibt. Ein Lambda zu deklarieren und es sofort aufzurufen, wäre eleganter, weniger Zeichen zu schreiben.
int output = ((Func<int>) (() => { return 1; }))();
public T Exec<T>(Func<T> func) => return func();
und ihn so verwenden:int x = Exec(() => { return 1; });
Das liest sich für mich viel schöner als das Casting mit all seinen Parens.Antworten:
Anstatt zu versuchen, das Lambda zu wirken, schlage ich vor, dass Sie eine kleine Hilfsfunktion verwenden:
die du dann so verwenden könntest :
int x = Exec(myVar => myVar + 2, 0);
. Das liest sich für mich viel besser als die hier vorgeschlagenen Alternativen.quelle
Es ist hässlich, aber es ist möglich:
Sie können werfen, aber das Lambda muss in Klammern stehen.
Das Obige kann ebenfalls vereinfacht werden:
quelle
int output = (Func<int>)(() => { return 1; })();
aber die Besetzung hat eine niedrigere Priorität als die Lambda-Ausführung.Lambda-Literale in C # unterscheiden sich merkwürdig darin, dass ihre Bedeutung von ihrem Typ abhängt. Sie sind bei ihrem Rückgabetyp im Wesentlichen überlastet, was in C # nirgendwo anders vorhanden ist. (Numerische Literale sind etwas ähnlich.)
Das exakt gleiche Lambda-Literal kann entweder eine anonyme Funktion auswerten, die Sie ausführen können (dh ein
Func
/Action
), oder eine abstrakte Darstellung der Operationen innerhalb des Körpers, ähnlich einem abstrakten Syntaxbaum (dh einem LINQ-Ausdrucksbaum).Letzteres ist beispielsweise die Funktionsweise von LINQ zu SQL, LINQ zu XML usw.: Die Lambdas werden nicht zu ausführbarem Code ausgewertet, sie werden zu LINQ-Ausdrucksbäumen ausgewertet, und der LINQ-Anbieter kann diese Ausdrucksbäume dann verwenden, um zu verstehen, was die Körper des Lambda macht und generiert zB eine SQL-Abfrage daraus.
In Ihrem Fall kann der Compiler nicht wissen, ob das Lambda-Literal zu einem
Func
oder einem LINQ-Ausdruck ausgewertet werden soll . Deshalb Johnathan Barclay Antwort Werke: es gibt einen Typ zum Ausdruck Lambda und damit der Compiler weiß , dass Sie einFunc
mit kompilierten Code, führt den Körper Ihrer Lambda statt einer nicht ausgewertet LINQ Expression Tree, repräsentiert den Code in der Körper des Lambda.quelle
Sie könnten die Deklaration des inline
Func
einfügenund sofort aufrufen.
quelle
Sie können den Alias auch in der
Select
Methode erstellenoder mit dem
??
Betreiberquelle
Wenn es Ihnen nichts ausmacht, gegen einige der Entwurfsrichtlinien für Erweiterungsmethoden zu verstoßen , können Erweiterungsmethoden in Kombination mit einem nullbedingten Operator
?.
Sie einigermaßen weit bringen:wird dir folgendes geben:
Wenn Sie hauptsächlich Arrays benötigen, überschreiben Sie die
ToArray
Erweiterungsmethode, um einige weitere Methodenaufrufe zu kapseln:ergebend:
quelle