Начиная с C# 3.0, доступен новый синтаксис для назначения реализации кода делегатам, называемый . Лямбда-выражения могут использоваться везде, где есть параметр типа делегата.
Синтаксис лямбда-выражений проще синтаксиса анонимных методов. В случае если подлежащий вызову метод имеет параметры, а эти параметры не нужны, синтаксис анонимных методов проще, поскольку в этом случае указывать параметры не потребуется.
Во всех лямбда-выражениях применяется новый лямбда-оператор =>, который разделяет лямбда-выражение на две части. В левой его части указывается входной параметр (или несколько параметров), а в правой части — тело лямбда-выражения. Оператор => иногда описывается такими словами, как "переходит" или "становится".
В C# поддерживаются две разновидности лямбда-выражений в зависимости от тела самого лямбда-выражения. Так, если тело лямбда-выражения состоит из одного выражения, то образуется одиночное лямбда-выражение. В этом случае тело выражения не заключается в фигурные скобки. Если же тело лямбда-выражения состоит из блока операторов, заключенных в фигурные скобки, то образуется блочное лямбда-выражение. При этом блочное лямбда-выражение может содержать целый ряд операторов, в том числе циклы, вызовы методов и условные операторы if. Обе разновидности лямбда-выражений рассматриваются далее по отдельности.
Содержание
- Одиночные лямбда-выражения
- Блочные лямбда-выражения
- Выражения-лямбды Expression lambdas
- Лямбды операторов Statement lambdas
- Асинхронные лямбда-выражения Async lambdas
- Лямбда-выражения и кортежи Lambda expressions and tuples
- Лямбда-выражения со стандартными операторами запросов Lambdas with the standard query operators
- Определение типа в лямбда-выражениях Type inference in lambda expressions
- Запись внешних переменных и области видимости переменной в лямбда-выражениях Capture of outer variables and variable scope in lambda expressions
Одиночные лямбда-выражения
В одиночном лямбда-выражении часть, находящаяся справа от оператора =>, воздействует на параметр (или ряд параметров), указываемый слева. Возвращаемым результатом вычисления такого выражения является результат выполнения лямбда-оператора. Ниже приведена общая форма одиночного лямбда-выражения, принимающего единственный параметр:
Если же требуется указать несколько параметров, то используется следующая форма:
Таким образом, когда требуется указать два параметра или более, их следует заключить в скобки. Если же выражение не требует параметров, то следует использовать пустые скобки.
Лямбда-выражение применяется в два этапа. Сначала объявляется тип делегата, совместимый с лямбда-выражением, а затем экземпляр делегата, которому присваивается лямбда-выражение. После этого лямбда-выражение вычисляется при обращении к экземпляру делегата. Результатом его вычисления становится возвращаемое значение. Давайте рассмотрим пример:

Блочные лямбда-выражения
Второй разновидностью лямбда-выражений является блочное лямбда-выражение. Для такого лямбда-выражения характерны расширенные возможности выполнения различных операций, поскольку в его теле допускается указывать несколько операторов. Например, в блочном лямбда-выражении можно использовать циклы и условные операторы if, объявлять переменные и т.д. Создать блочное лямбда-выражение нетрудно. Для этого достаточно заключить тело выражения в фигурные скобки. Помимо возможности использовать несколько операторов, в остальном блочное лямбда-выражение, практически ничем не отличается от только что рассмотренного одиночного лямбда-выражения.
Давайте модифицируем предыдущий пример, добавив капчу в форму регистрации:
Опубликовано: Октябрь 2016
| Примечание |
|---|
Последние версии документации по C# см. в руководстве по C# на сайте docs.microsoft.com.
Лямбда-выражение — это анонимная функция, с помощью которой можно создавать типы делегатов или деревьев выражений. С помощью лямбда-выражений можно писать локальные функции, которые можно передавать в качестве аргументов или возвращать в качестве значений из вызовов функций. Лямбда-выражения особенно полезны при написании выражений запросов LINQ.
Чтобы создать лямбда-выражение, необходимо указать входные параметры (если они есть) с левой стороны лямбда-оператора =>, и поместить блок выражений или операторов с другой стороны. Например, лямбда-выражение x => x * x задает параметр с именем x и возвращает значение x . Можно назначить это выражение типу делегата, как показано в следующем примере:
Создание типа дерева выражений:
Оператор => имеет такой же приоритет, как и присваивание ( = ), и является правоассоциативным (см. раздел "Ассоциативность" статьи об операторах).
Лямбда-операторы используются в запросах LINQ на основе методов в качестве аргументов стандартных методов операторов запроса, таких как Where .
При использовании синтаксиса на основе методов для вызова метода Where в классе Enumerable (как это делается в LINQ на объекты и LINQ to XML) параметром является тип делегата System.Func . Лямбда-выражение — это наиболее удобный способ создания делегата. При вызове того же метода, к примеру, в классе System.Linq.Queryable (как это делается в LINQ to SQL) типом параметра будет System.Linq.Expressions.Expression , где Func — это любые делегаты Func с числом входных параметров не более шестнадцати. Опять же, лямбда-выражения представляют собой самый быстрый способ построения дерева выражений. Лямбда-выражения позволяют вызовам Where выглядеть одинаково, хотя на самом деле объект, созданный из лямбда-выражения, имеет другой тип.
Обратите внимание: в приведенном выше примере сигнатура делегата имеет один неявный входной параметр типа int и возвращает значение типа int . Лямбда-выражение можно преобразовать в делегат соответствующего типа, поскольку он также имеет один входной параметр ( x ) и возвращает значение, которое компилятор может неявно преобразовать в тип int . (Вывод типов более подробно рассматривается в следующих разделах.) Делегат, вызываемый посредством входного параметра 5, возвращает результат 25.
Лямбда-выражения нельзя использовать с левой стороны оператора is или as.
Все ограничения, применяемые к анонимным методам, применяются также к лямбда-выражениям. Для получения дополнительной информации см. Анонимные методы.
Лямбда-выражение с выражением с правой стороны оператора => называется выражением-лямбдой. Выражения-лямбды широко используются при конструировании Деревья выражений. Выражения-лямбды возвращают результат выражения и принимают следующую основную форму.
Если лямбда-выражение имеет только один входной параметр, скобки можно не ставить; во всех остальных случаях они обязательны. Два и более входных параметра разделяются запятыми и заключаются в скобки:
Иногда компилятору бывает трудно или даже невозможно определить входные типы. В этом случае типы можно указать в явном виде, как показано в следующем примере.
Нулевое количество входных параметры задается пустыми скобками:
Обратите внимание, что тело выражения-лямбды может состоять из вызова метода, как было показано в предыдущем примере. Однако при создании деревьев выражений, которые вычисляются вне .NET Framework, например в SQL Server, не следует использовать вызовы методов в лямбда-выражениях. Эти методы не имеют смысла вне контекста среды CLR .NET.
Лямбда оператора напоминает выражение-лямбду, за исключением того, что оператор (или операторы) заключается в фигурные скобки:
Тело лямбды оператора может состоять из любого количества операторов; однако на практике обычно используется не более двух-трех.
Лямбды операторов, как и анонимные методы, не могут использоваться для создания деревьев выражений.
С помощью ключевых слов async и await можно легко создавать лямбда-выражения и операторы, включающие асинхронную обработку. Например, в следующем примере Windows Forms содержится обработчик событий, который вызывает асинхронный метод ExampleMethodAsync и ожидает его.
Такой же обработчик событий можно добавить с помощью асинхронного лямбда-выражения. Чтобы добавить этот обработчик, поставьте модификатор async перед списком параметров лямбда-выражения, как показано в следующем примере.
Дополнительные сведения о создании и использовании асинхронных методов см. в разделе Асинхронное программирование с использованием ключевых слов Async и Await.
Многие стандартные операторы запросов имеют входной параметр, тип которого принадлежит к семейству Func универсальных делегатов. Эти делегаты используют параметры типа для определения количества и типов входных параметров, а также тип возвращаемого значения делегата. Делегаты Func очень полезны для инкапсуляции пользовательских выражений, которые применяются к каждому элементу в наборе исходных данных. В качестве примера рассмотрим следующий тип делегата.
Экземпляр этого делегата можно создать как Func myFunc , где int — входной параметр, а bool — возвращаемое значение. Возвращаемое значение всегда указывается в последнем параметре типа. Func определяет делегат с двумя входными параметрами, int и string , и типом возвращаемого значения bool . Следующий делегат Func при вызове возвращает значение true или false, которое показывает, равен ли входной параметр 5.
Также лямбда-выражения можно использовать, когда аргумент имеет тип Expression , например в стандартных операторах запросов, как указано в System.Linq.Queryable. При определении аргумента Expression лямбда компилируется в дерево выражений.
Ниже показан метод Count , являющийся стандартным оператором запроса.
Компилятор может вывести тип входного параметра ввода; но его также можно определить явным образом. Данное лямбда-выражение подсчитывает указанные целые значения ( n ), которые при делении на два дают остаток 1.
Следующая строка кода создает последовательность, которая содержит все элементы массива numbers , расположенные слева от 9, поскольку это первое число последовательности, не удовлетворяющее условию:
В этом примере показано, как определить несколько входных параметров путем их заключения в скобки. Этот метод возвращает все элементы в массиве чисел до того числа, величина которого меньше номера его позиции. Не следует путать лямбда-оператор ( => ) с оператором "больше или равно" ( >= ).
При написании лямбда-выражений обычно не требуется указывать тип входных параметров, поскольку компилятор может выводить этот тип на основе тела лямбда-выражения, типа делегата параметра и других факторов, как описано в спецификации языка C#. Для большинства стандартных операторов запросов первой входное значение имеет тип элементов в исходной последовательности. Поэтому при запросе IEnumerable входная переменная считается объектом Customer , а это означает, что у вас есть доступ к его методам и свойствам.
Общие правила для лямбда-выражений формулируются следующим образом:
лямбда-выражение должно содержать то же число параметров, что и тип делегата;
каждый входной параметр в лямбда-выражении должен быть неявно преобразуемым в соответствующий параметр делегата;
возвращаемое значение лямбда-выражения (если таковое имеется) должно быть неявно преобразуемым в возвращаемый тип делегата.
Обратите внимание: лямбда-выражения сами по себе не имеют типа, поскольку в системе общих типов изначально отсутствует понятие "лямбда-выражения". Однако иногда бывает удобно оперировать понятием "типа" применительно к лямбда-выражениям. При этом под типом понимается тип делегата или тип Expression, в который преобразуется лямбда-выражение.
Лямбда-выражения могут ссылаться на внешние переменные (см. Анонимные методы), находящиеся в области метода, в котором определена лямбда-функция, или в области типа, который содержит лямбда-выражение. Переменные, полученные таким способом, сохраняются для использования в лямбда-выражениях, даже если бы в ином случае они оказались за границами области действия и уничтожились сборщиком мусора. Внешняя переменная должна быть определенным образом присвоена, прежде чем она сможет использоваться в лямбда-выражениях. В следующем примере демонстрируются эти правила.
Следующие правила применимы к области действия переменной в лямбда-выражениях.
Захваченная переменная не будет уничтожена сборщиком мусора до тех пор, пока делегат, который на нее ссылается, не перейдет в статус подлежащего уничтожению при сборке мусора.
Переменные, вводимые в лямбда-выражении, невидимы во внешнем методе.
Лямбда-выражение не может непосредственно захватывать параметры ref или out из метода, в котором они находятся.
Оператор return в лямбда-выражении не вызывает возвращение значения внешним методом.
Лямбда-выражение не может содержать оператора goto , оператора break или оператора continue внутри лямбда-функции, если целевой объект перехода находится вне блока. Если целевой объект находится внутри блока, то наличие оператора перехода за пределами лямбда-функции также будет ошибкой.
Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
Лямбда-выражение является выражением любой из следующих двух форм: A lambda expression is an expression of any of the following two forms:
Лямбда выражения, имеющая выражение в качестве текста: Expression lambda that has an expression as its body:
Лямбда оператора, имеющая блок операторов в качестве текста: Statement lambda that has a statement block as its body:
Используйте оператор объявления лямбда-выражения => для отделения списка параметров лямбда-выражения от исполняемого кода. Use the lambda declaration operator => to separate the lambda’s parameter list from its body. Чтобы создать лямбда-выражение, необходимо указать входные параметры (если они есть) с левой стороны лямбда-оператора и блок выражений или операторов с другой стороны. To create a lambda expression, you specify input parameters (if any) on the left side of the lambda operator and an expression or a statement block on the other side.
Лямбда-выражение может быть преобразовано в тип делегата. Any lambda expression can be converted to a delegate type. Тип делегата, в который может быть преобразовано лямбда-выражение, определяется типами его параметров и возвращаемым значением. The delegate type to which a lambda expression can be converted is defined by the types of its parameters and return value. Если лямбда-выражение не возвращает значение, оно может быть преобразовано в один из типов делегата Action ; в противном случае его можно преобразовать в один из типов делегатов Func . If a lambda expression doesn’t return a value, it can be converted to one of the Action delegate types; otherwise, it can be converted to one of the Func delegate types. Например, лямбда-выражение, которое имеет два параметра и не возвращает значение, можно преобразовать в делегат Action . For example, a lambda expression that has two parameters and returns no value can be converted to an Action delegate. Лямбда-выражение, которое имеет два параметра и возвращает значение, можно преобразовать в делегат Func . A lambda expression that has one parameter and returns a value can be converted to a Func delegate. В следующем примере лямбда-выражение x => x * x , которое указывает параметр с именем x и возвращает значение x в квадрате, присваивается переменной типа делегата: In the following example, the lambda expression x => x * x , which specifies a parameter that’s named x and returns the value of x squared, is assigned to a variable of a delegate type:
Лямбда выражений также можно преобразовать в типы дерева выражения, как показано в следующем примере: Expression lambdas also can be converted to the expression tree types, as the following example shows:
Лямбда-выражения можно использовать в любом коде, для которого требуются экземпляры типов делегатов или деревьев выражений, например в качестве аргумента метода Task.Run(Action) для передачи кода, который должен выполняться в фоновом режиме. You can use lambda expressions in any code that requires instances of delegate types or expression trees, for example as an argument to the Task.Run(Action) method to pass the code that should be executed in the background. Можно также использовать лямбда-выражения при написании выражений запросов LINQ, как показано в следующем примере: You also can use lambda expressions when you write LINQ query expressions, as the following example shows:
При использовании синтаксиса на основе методов для вызова метода Enumerable.Select в классе System.Linq.Enumerable (например, в LINQ to Objects и LINQ to XML) параметром является тип делегата System.Func . When you use method-based syntax to call the Enumerable.Select method in the System.Linq.Enumerable class, for example in LINQ to Objects and LINQ to XML, the parameter is a delegate type System.Func . При вызове метода Queryable.Select в классе System.Linq.Queryable (например, в LINQ to SQL) типом параметра является тип дерева выражения Expression > . When you call the Queryable.Select method in the System.Linq.Queryable class, for example in LINQ to SQL, the parameter type is an expression tree type Expression > . В обоих случаях можно использовать одно и то же лямбда-выражение для указания значения параметра. In both cases you can use the same lambda expression to specify the parameter value. Поэтому оба вызова Select выглядят одинаково, хотя на самом деле объект, созданный из лямбда-выражения, имеет другой тип. That makes the two Select calls to look similar although in fact the type of objects created from the lambdas is different.
Выражения-лямбды Expression lambdas
Лямбда-выражение с выражением с правой стороны оператора => называется выражением лямбда. A lambda expression with an expression on the right side of the => operator is called an expression lambda. Выражения-лямбды широко используются при конструировании деревьев выражений. Expression lambdas are used extensively in the construction of expression trees. Выражения-лямбды возвращают результат выражения и принимают следующую основную форму. An expression lambda returns the result of the expression and takes the following basic form:
Если лямбда-выражение имеет только один входной параметр, скобки можно не ставить; во всех остальных случаях они обязательны. The parentheses are optional only if the lambda has one input parameter; otherwise they are required.
Нулевое количество входных параметры задается пустыми скобками: Specify zero input parameters with empty parentheses:
Два и более входных параметра разделяются запятыми и заключаются в скобки: Two or more input parameters are separated by commas enclosed in parentheses:
Иногда компилятору не удается определить входные типы. Sometimes it’s impossible for the compiler to infer the input types. Вы можете указать типы данных в явном виде, как показано в следующем примере: You can specify the types explicitly as shown in the following example:
Для входных параметров все типы нужно задать либо в явном, либо в неявном виде. В противном случае компилятор выдает ошибку CS0748. Input parameter types must be all explicit or all implicit; otherwise, a CS0748 compiler error occurs.
Текст выражения лямбды может состоять из вызова метода. The body of an expression lambda can consist of a method call. Но при создании деревьев выражений, которые вычисляются вне контекста поддержки общеязыковой среды выполнения .NET, например в SQL Server, вызовы методов не следует использовать в лямбда-выражениях. However, if you are creating expression trees that are evaluated outside the context of the .NET common language runtime, such as in SQL Server, you should not use method calls in lambda expressions. Эти методы не имеют смысла вне контекста среды CLR .NET. The methods will have no meaning outside the context of the .NET common language runtime.
Лямбды операторов Statement lambdas
Лямбда оператора напоминает выражение-лямбду, за исключением того, что оператор (или операторы) заключается в фигурные скобки: A statement lambda resembles an expression lambda except that the statement(s) is enclosed in braces:
Тело лямбды оператора может состоять из любого количества операторов; однако на практике обычно используется не более двух-трех. The body of a statement lambda can consist of any number of statements; however, in practice there are typically no more than two or three.
Лямбды операторов нельзя использовать для создания деревьев выражений. Statement lambdas cannot be used to create expression trees.
Асинхронные лямбда-выражения Async lambdas
С помощью ключевых слов async и await можно легко создавать лямбда-выражения и операторы, включающие асинхронную обработку. You can easily create lambda expressions and statements that incorporate asynchronous processing by using the async and await keywords. Например, в следующем примере Windows Forms содержится обработчик событий, который вызывает асинхронный метод ExampleMethodAsync и ожидает его. For example, the following Windows Forms example contains an event handler that calls and awaits an async method, ExampleMethodAsync .
Такой же обработчик событий можно добавить с помощью асинхронного лямбда-выражения. You can add the same event handler by using an async lambda. Чтобы добавить этот обработчик, поставьте модификатор async перед списком параметров лямбда-выражения, как показано в следующем примере: To add this handler, add an async modifier before the lambda parameter list, as the following example shows:
Дополнительные сведения о создании и использовании асинхронных методов см. в разделе Асинхронное программирование с использованием ключевых слов Async и Await. For more information about how to create and use async methods, see Asynchronous Programming with async and await.
Лямбда-выражения и кортежи Lambda expressions and tuples
В C# 7.0 представлена встроенная поддержка кортежей. Starting with C# 7.0, the C# language provides built-in support for tuples. Кортеж можно ввести в качестве аргумента лямбда-выражения, и лямбда-выражение также может возвращать кортеж. You can provide a tuple as an argument to a lambda expression, and your lambda expression can also return a tuple. В некоторых случаях компилятор C# использует определение типа для определения типов компонентов кортежа. In some cases, the C# compiler uses type inference to determine the types of tuple components.
Кортеж определяется путем заключения в скобки списка его компонентов с разделителями-запятыми. You define a tuple by enclosing a comma-delimited list of its components in parentheses. В следующем примере кортеж с тремя компонентами используется для передачи последовательности чисел в лямбда-выражение. Оно удваивает каждое значение и возвращает кортеж с тремя компонентами, содержащий результат операций умножения. The following example uses tuple with three components to pass a sequence of numbers to a lambda expression, which doubles each value and returns a tuple with three components that contains the result of the multiplications.
Как правило, поля кортежи именуются как Item1 , Item2 и т. д. Тем не менее кортеж с именованными компонентами можно определить, как показано в следующем примере: Ordinarily, the fields of a tuple are named Item1 , Item2 , etc. You can, however, define a tuple with named components, as the following example does.
См. дополнительные сведения о типах кортежей в C#. For more information about C# tuples, see C# tuple types.
Лямбда-выражения со стандартными операторами запросов Lambdas with the standard query operators
Экземпляр этого делегата можно создать как Func , где int — входной параметр, а bool — возвращаемое значение. The delegate can be instantiated as a Func instance where int is an input parameter and bool is the return value. Возвращаемое значение всегда указывается в последнем параметре типа. The return value is always specified in the last type parameter. Например, Func определяет делегат с двумя входными параметрами, int и string , и типом возвращаемого значения bool . For example, Func defines a delegate with two input parameters, int and string , and a return type of bool . Следующий делегат Func при вызове возвращает логическое значение, которое показывает, равен ли входной параметр 5: The following Func delegate, when it’s invoked, returns Boolean value that indicates whether the input parameter is equal to five:
В этом примере используется стандартный оператор запроса Count: The following example uses the Count standard query operator:
Компилятор может вывести тип входного параметра ввода; но его также можно определить явным образом. The compiler can infer the type of the input parameter, or you can also specify it explicitly. Данное лямбда-выражение подсчитывает указанные целые значения ( n ), которые при делении на два дают остаток 1. This particular lambda expression counts those integers ( n ) which when divided by two have a remainder of 1.
В следующем примере кода показано, как создать последовательность, которая содержит все элементы массива numbers , предшествующие 9, так как это первое число последовательности, не удовлетворяющее условию: The following example produces a sequence that contains all elements in the numbers array that precede the 9, because that’s the first number in the sequence that doesn’t meet the condition:
В следующем примере показано, как указать несколько входных параметров путем их заключения в скобки. The following example specifies multiple input parameters by enclosing them in parentheses. Этот метод возвращает все элементы в массиве numbers до того числа, значение которого меньше его порядкового номера в массиве: The method returns all the elements in the numbers array until it encounters a number whose value is less than its ordinal position in the array:
Определение типа в лямбда-выражениях Type inference in lambda expressions
При написании лямбда-выражений обычно не требуется указывать тип входных параметров, так как компилятор может выводить этот тип на основе тела лямбда-выражения, типов параметров и других факторов, как описано в спецификации языка C#. When writing lambdas, you often don’t have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter types, and other factors as described in the C# language specification. Для большинства стандартных операторов запросов первой входное значение имеет тип элементов в исходной последовательности. For most of the standard query operators, the first input is the type of the elements in the source sequence. При запросе IEnumerable входная переменная считается объектом Customer , а это означает, что у вас есть доступ к его методам и свойствам. If you are querying an IEnumerable , then the input variable is inferred to be a Customer object, which means you have access to its methods and properties:
Общие правила определения типа для лямбда-выражений формулируются следующим образом: The general rules for type inference for lambdas are as follows:
лямбда-выражение должно содержать то же число параметров, что и тип делегата; The lambda must contain the same number of parameters as the delegate type.
каждый входной параметр в лямбда-выражении должен быть неявно преобразуемым в соответствующий параметр делегата; Each input parameter in the lambda must be implicitly convertible to its corresponding delegate parameter.
возвращаемое значение лямбда-выражения (если таковое имеется) должно быть неявно преобразуемым в возвращаемый тип делегата. The return value of the lambda (if any) must be implicitly convertible to the delegate’s return type.
Обратите внимание, что у лямбда-выражений нет типа, так как в системе общих типов изначально отсутствует такое понятие, как лямбда-выражения. Note that lambda expressions in themselves don’t have a type because the common type system has no intrinsic concept of "lambda expression." Но применительно к лямбда-выражениям иногда бывает удобно оперировать понятием типа. However, it’s sometimes convenient to speak informally of the "type" of a lambda expression. При этом под типом понимается тип делегата или тип Expression , в который преобразуется лямбда-выражение. In these cases the type refers to the delegate type or Expression type to which the lambda expression is converted.
Запись внешних переменных и области видимости переменной в лямбда-выражениях Capture of outer variables and variable scope in lambda expressions
Лямбда-выражения могут ссылаться на внешние переменные. Lambdas can refer to outer variables. Это переменные в области метода, в котором определено лямбда-выражение, или области типа, который содержит лямбда-выражение. These are the variables that are in scope in the method that defines the lambda expression, or in scope in the type that contains the lambda expression. Переменные, полученные таким способом, сохраняются для использования в лямбда-выражениях, даже если бы в ином случае они оказались за границами области действия и уничтожились сборщиком мусора. Variables that are captured in this manner are stored for use in the lambda expression even if the variables would otherwise go out of scope and be garbage collected. Внешняя переменная должна быть определенным образом присвоена, прежде чем она сможет использоваться в лямбда-выражениях. An outer variable must be definitely assigned before it can be consumed in a lambda expression. В следующем примере демонстрируются эти правила. The following example demonstrates these rules:
Следующие правила применимы к области действия переменной в лямбда-выражениях. The following rules apply to variable scope in lambda expressions:
Захваченная переменная не будет уничтожена сборщиком мусора до тех пор, пока делегат, который на нее ссылается, не перейдет в статус подлежащего уничтожению при сборке мусора. A variable that is captured will not be garbage-collected until the delegate that references it becomes eligible for garbage collection.
Переменные, представленные в лямбда-выражении, невидимы в заключающем методе. Variables introduced within a lambda expression are not visible in the enclosing method.
Лямбда-выражение не может непосредственно захватывать параметры in, ref или out из заключающего метода. A lambda expression cannot directly capture an in, ref, or out parameter from the enclosing method.
Оператор return в лямбда-выражении не вызывает возврат значения заключающим методом. A return statement in a lambda expression doesn’t cause the enclosing method to return.
Лямбда-выражение не может содержать операторы goto, break или continue, если целевой объект этого оператора перехода находится за пределами блока лямбда-выражения. A lambda expression cannot contain a goto, break, or continue statement if the target of that jump statement is outside the lambda expression block. Если целевой объект находится внутри блока, использование оператора перехода за пределами лямбда-выражения также будет ошибкой. It’s also an error to have a jump statement outside the lambda expression block if the target is inside the block.






