Улучшения Лямбда-Выражений в C# 10
Последний (по крайней мере пока) пост о новинках в новой версии C#. На всякий случай вот предыдущие посты о C# 10 и .NET 6:
- Улучшения в Асинхронности
- Улучшения в LINQ 1, 2
- PriorityQueue
- Статические абстрактные члены интерфейсов
- Обобщённая математика
- IEnumerable.Chunk()
- Глобальные Директивы Using
- Неявные Директивы Using
- Изменения в Структурах
- Улучшения Интерполяции Строк
Выведение типа в лябмдах
Лямбда-выражения теперь могут иметь «естественный» тип, то есть компилятор часто может самостоятельно определить тип лямбда-выражения. До сих пор лямбда-выражение приходилось преобразовывать в тип делегата или выражения. В большинстве случаев вы использовали один из перегруженных типов делегатов Func<…> или Action<…>:
Func<string, int> parse = (string s) => int.Parse(s);Начиная с C# 10 компилятор может вывести тип за вас. Вы можете навести курсор на переменную и убедиться, что её тип всё так же
Func<string, int>:var parse = (string s) => int.Parse(s);Обычно компилятор будет использовать доступный делегат
Func или Action, если подходящий существует. В противном случае он будет синтезировать тип делегата (например, если у вас есть ref-параметры или большое количество параметров). Не все лямбды имеют естественные типы - некоторым просто не хватает информации о типах. Например, если не указывать типы параметров, компилятор не сможет решить, какой тип делегата использовать, что приведёт к ошибке компиляции:var parse = s => int.Parse(s);Вывод естественного типа лямбды означает, что она может быть присвоена более базовому типу, например,
object или Delegate:Delegate parse = (string s) => int.Parse(s);В деревьях выражений используется комбинация «целевой» и «естественной» типизации. Если целевым типом является
LambdaExpression или необобщённый Expression (базовый тип для всех деревьев выражений), а лямбда имеет естественный тип делегата D, будет выведен тип Expression<D>:Expression parseExpr = (string s) => int.Parse(s);Здесь для
parseExpr будет выведен тип Expression<Func<string, int>>.Типы возврата для лямбда-выражений
В предыдущих примерах тип возвращаемого значения лямбда-выражения был очевиден и выводился. Это не всегда так:
var choose = (bool b) => b ? 1 : "two";В C# 10 вы можете указать явный тип возвращаемого значения для лямбда-выражения прямо перед параметрами. При этом параметры должны быть заключены в круглые скобки:
// Ошибка, т.к. тип результата непонятен
var choose = object (bool b) => b ? 1 : "two";Атрибуты лямбда-выражений
// Func<bool, object>
Теперь вы можете помещать атрибуты в лямбда-выражения так же, как для методов и локальных функций. Cписок параметров при этом также должен быть заключен в круглые скобки:
Func<string, int> parse =Как и для локальных функции, к лямбдам могут применяться только атрибуты, имеющие
[Example(1)] (s) => int.Parse(s);
var choose =
[Example(2)][Example(3)] object (bool b)
=> b ? 1 : "two";
AttributeTargets.Method.Лямбда-выражения вызываются иначе, чем методы и локальные функции, и в результате атрибуты не имеют эффекта при вызове лямбда-выражения. Однако атрибуты лямбда-выражений по-прежнему полезны для анализа кода, и они также генерируются в методах, которые компилятор генерирует для лямбда-выражений, так что их можно обнаружить с помощью рефлексии.
Источник: https://devblogs.microsoft.com/dotnet/welcome-to-csharp-10/