Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp_Prog_Guide.doc
Скачиваний:
16
Добавлен:
16.11.2019
Размер:
6.22 Mб
Скачать

Вывод типа в лямбда-выражениях

При написании лямбда-выражений обычно не требуется указывать тип параметров ввода, поскольку компилятор может вывести этот тип на основе тела лямбда-выражения, лежащего в его основе типа делегата и других факторов, как описано в спецификации языка C# 3.0. Для большинства стандартных операторов запроса первый ввод имеет тип элементов в исходной последовательности. Поэтому, если производится запрос IEnumerable<Customer>, переменная ввода расценивается как объект Customer, а это означает, что у вас есть доступ к его методам и свойствам.

customers.Where(c => c.City == "London");

Используются следующие основные правила для лямбда-выражений.

  • Лямбда-выражение должно содержать то же число параметров, что и тип делегата.

  • Каждый параметр ввода в лямбда-выражении должен быть неявно преобразуемым в соответствующий параметр делегата.

  • Возвращаемое значение лямбда-выражения (если таковое имеется) должно быть неявно преобразуемым в возвращаемый тип делегата.

Обратите внимание: лямбда-выражения сами по себе не имеют типа, поскольку система общих типов не имеет внутреннего принципа "лямбда-выражения". Однако иногда бывает удобно оперировать понятием "типа" лямбда-выражения. При этом под типом понимается тип делегата или тип Expression, в который преобразуется лямбда-выражение.

Variable Scope in Lambda Expressions

Lambdas can refer to outer variables that are in scope in the enclosing method or type in which the lambda is defined. Variables that are captured in this manner are stored for use in the lambda expression even if 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:

delegate bool D();

delegate bool D2(int i);

class Test

{

D del;

D2 del2;

public void TestMethod(int input)

{

int j = 0;

// Initialize the delegates with lambda expressions.

// Note access to 2 outer variables.

// del will be invoked within this method.

del = () => { j = 10; return j > input; };

// del2 will be invoked after TestMethod goes out of scope.

del2 = (x) => {return x == j; };

// Demonstrate value of j:

// Output: j = 0

// The delegate has not been invoked yet.

Console.WriteLine("j = {0}", j);

// Invoke the delegate.

bool boolResult = del();

// Output: j = 10 b = True

Console.WriteLine("j = {0}. b = {1}", j, boolResult);

}

static void Main()

{

Test test = new Test();

test.TestMethod(5);

// Prove that del2 still has a copy of

// local variable j from TestMethod.

bool result = test.del2(10);

// Output: True

Console.WriteLine(result);

Console.ReadKey();

}

}