Можно объявить лямбда-функцию и немедленно вызвать ее:
Func<int, int> lambda = (input) => { return 1; };
int output = lambda(0);
Мне интересно, если это возможно сделать в одну строку, например что-то вроде
int output = (input) => { return 1; }(0);
что выдает ошибку компилятора "Ожидается имя метода". Приведение к Func<int, int>
не работает:
int output = (Func<int, int>)((input) => { return 1; })(0);
выдает ту же ошибку, и по причинам, указанным ниже, я бы хотел избежать необходимости явно указывать тип входного аргумента (первый int
).
Вы, наверное, задаетесь вопросом, почему я хочу сделать это, а не просто встраивать код, например int output = 1;
. Причина в следующем: я сгенерировал ссылку на веб-сервис SOAP svcutil
, который из-за вложенных элементов генерирует очень длинные имена классов, которые я хотел бы избежать при наборе. Так что вместо
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()
};
и отдельный CreateAddress(GetOrderResultOrderShipment_OrderShipmentShipment_Address address)
метод (реальные имена еще длиннее, и у меня очень ограниченный контроль над формой), я хотел бы написать
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()
};
Я знаю, что мог бы написать
Address = sh.ReceiverAddress_Shipment == null ? null : new Address {
Street = sh.ReceiverAddress_Shipment.Address.Street,
...
}
но даже это ( sh.ReceiverAddress_Shipment.Address
часть) становится очень повторяющимся, если есть много полей. Объявление лямбды и немедленный вызов ее будет более изящным, чем писать меньше символов.
int output = ((Func<int>) (() => { return 1; }))();
public T Exec<T>(Func<T> func) => return func();
и использовать ее так: «int x = Exec(() => { return 1; });
Мне кажется, это намного лучше, чем кастинг со всеми его паренами».Ответы:
Вместо того, чтобы пытаться разыграть лямбду, я предлагаю вам использовать небольшую вспомогательную функцию:
которые вы могли бы использовать , как это:
int x = Exec(myVar => myVar + 2, 0);
. Это звучит намного лучше для меня, чем предлагаемые здесь альтернативы.источник
Это некрасиво, но возможно
Вы можете разыграть, но лямбда должна быть заключена в скобки.
Вышесказанное также может быть упрощено:
источник
int output = (Func<int>)(() => { return 1; })();
но приведение имеет более низкий приоритет, чем лямбда-исполнение.Лямбда-литералы в C # имеют любопытное различие в том, что их значение зависит от их типа. Они по существу перегружены своим типом возврата, который в C # больше нигде не существует. (Числовые литералы несколько похожи.)
Точно такой же лямбда буквальным может либо вычисляться анонимной функции , которые можно выполнить (т.е.
Func
/Action
) или абстрактное представление операций внутри тела, вроде как абстрактное синтаксическое дерево (т.е. LINQ Expression Tree).Последнее является, например, как LINQ к SQL, LINQ к XML и т.д. работы: лямбды не оценивают исполняемый код, они оценивают деревья выражений LINQ, и поставщик LINQ может затем использовать эти деревья выражений, чтобы понять, что тело лямбда делает и генерирует, например, SQL-запрос из этого.
В вашем случае у компилятора нет возможности узнать, должен ли лямбда-литерал быть оценен в
Func
выражении LINQ или. Вот почему ответ Джонатана Барклая работает: он задает тип лямбда-выражения, и поэтому компилятор знает, что вам нуженFunc
компилированный код, который выполняет тело вашей лямбды, а не необработанное дерево выражений LINQ, представляющее код внутри тело лямбды.источник
Вы могли бы встроить декларацию
Func
, выполниви немедленно вызывать его.
источник
Вы также можете создать псевдоним в
Select
методеили с
??
операторомисточник
Если вы не возражаете нарушить некоторые рекомендации по разработке методов расширения, методы расширения в сочетании с нулевым условным оператором
?.
могут привести вас довольно далеко:даст вам это:
и если вам в основном нужны массивы, переопределите
ToArray
метод расширения, чтобы инкапсулировать еще несколько вызовов метода:в результате чего:
источник