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

Анонимные функции

Как описано в других разделах, делегат — это тип, создающий оболочку вызова метода. Экземпляр делегата можно подставлять между методами как тип и вызывать как метод. Анонимная функция – это оператор или выражение "inline", которое можно использовать каждый раз, когда ожидается тип делегата. Ее можно использовать для инициализации именованного делегата или подставить вместо типа именованного делегата в качестве параметра метода.

Существует два типа анонимных функций, каждый из которых по отдельности рассматривается в следующих разделах:

  • Лямбда-выражения.

  • Анонимные методы.

Примечание.

Лямбда-выражения можно привязать к деревьям выражений и к делегатам.

Эволюция делегатов в c#

В языке C# 1.0 разработчик создавал экземпляр делегата путем его явной инициализации с методом, определенным в каком-либо месте кода. В C# версии 2.0 представлена концепция анонимных методов, которые позволяют писать блоки неименованных встраиваемых выражений, которые можно выполнять в вызове делегата. В языке C# версии 3.0 представлены лямбда-выражения, концепция которых соответствует анонимным методам, но которые являются более выразительными и лаконичными. Две эти возможности вместе называются анонимными функциями. В общем, в приложениях для среды .NET Framework версии 3.5 и более новой версии должны использоваться лямбда-выражения.

В приведенном ниже примере демонстрируется эволюция создания делегата в языке C# с версии 1.0 до версии 3.0.

class Test

{

delegate void TestDelegate(string s);

static void M(string s)

{

Console.WriteLine(s);

}

static void Main(string[] args)

{

// Original delegate syntax required

// initialization with a named method.

TestDelegate testdelA = new TestDelegate(M);

// C# 2.0: A delegate can be initialized with

// inline code, called an "anonymous method." This

// method takes a string as an input parameter.

TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };

// C# 3.0. A delegate can be initialized with

// a lambda expression. The lambda also takes a string

// as an input parameter (x). The type of x is inferred by the compiler.

TestDelegate testDelC = (x) => { Console.WriteLine(x); };

// Invoke the delegates.

testdelA("Hello. My name is M and I write lines.");

testDelB("That's nothing. I'm anonymous and ");

testDelC("I'm a famous author.");

// Keep console window open in debug mode.

Console.WriteLine("Press any key to exit.");

Console.ReadKey();

}

}

/* Output:

Hello. My name is M and I write lines.

That's nothing. I'm anonymous and

I'm a famous author.

Press any key to exit.

*/

------ Пример

Lambda Expressions

A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.

All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block. The lambda expression x => x * x is read "x goes to x times x." This expression can be assigned to a delegate type as follows:

delegate int del(int i);

del myDelegate = x => x * x;

int j = myDelegate(5); //j = 25

To create an expression tree type:

using System.Linq.Expressions;

// ...

Expression<del> = x => x * x;

The => operator has the same precedence as assignment (=) and is right-associative.

Lambdas are used in method-based LINQ queries as arguments to standard query operator methods such as Where and Where(IQueryable, String, array<Object>[]()[]).

When you use method-based syntax to call the Where method in the Enumerable class (as you do in LINQ to Objects and LINQ to XML) the parameter is a delegate type Func<(Of <(T, TResult>)>). A lambda expression is the most convenient way to create that delegate. When you call the same method in, for example, the Queryable class (as you do in LINQ to SQL) then the parameter type is an Expression<Func> where Func is any Func delegates with up to five input parameters. Again, a lambda expression is just a very concise way to construct that expression tree. The lambdas allow the Where calls to look similar although in fact the type of object created from the lambda is different.

In the previous example, notice that the delegate signature has one implicitly-typed input parameter of type int, and returns an int. The lambda expression can be converted to a delegate of that type because it also has one input parameter (x) and a return value that the compiler can implicitly convert to type int. (Type inference is discussed in more detail in the following sections.) When the delegate is invoked by using an input parameter of 5, it returns a result of 25.

Lambdas are not allowed on the left side of the is or as operator.

All restrictions that apply to anonymous methods also apply to lambda expressions. For more information, see Anonymous Methods.