Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка ПИ Программирование на С# _Хотов.docx
Скачиваний:
4
Добавлен:
01.07.2025
Размер:
2.22 Mб
Скачать
      1. Анонимные методы

С делегатами тесно связано понятие анонимных методов. Анонимные методы представляют сокращенную запись методов. Например, в прошлой теме мы создавали событие и обработчик к нему, который выглядел следующим образом:

private static void Show_Message(object sender, AccountEventArgs e)

{

Console.WriteLine("Сумма транзакции: {0}", e.sum);

Console.WriteLine(e.message);

}

Иногда такие методы нужны для обработки одного события и больше ценности не представляют и нигде не используются. Анонимные методы позволяют встроить код там, где он вызывается, например:

Account account = new Account(200, 6);

// Добавляем обработчики события

account.Added += delegate(object sender, AccountEventArgs e)

{

Console.WriteLine("Сумма транзакции: {0}", e.sum);

Console.WriteLine(e.message);

};

Практически этот тот же самый метод, только встроенный в код. Встраивание происходит с помощью ключевого слова delegate, после которого идет список параметров и далее сам код анонимного метода. Итоговый результат будет такой же, как будто мы подключали обработчик события Show_Message.

И важно отметить, что в отличие от блока методов или условных и циклических конструкций, блок анонимных методов должен заканчиваться точкой с запятой после закрывающей фигурной скобки.

Если для анонимного метода не требуется параметров, то он используется без скобок:

delegate void GetMessage();

static void Main(string[] args)

{

GetMessage message = delegate

{

Console.WriteLine("анонимный делегат");

};

message();

Console.Read();

}

      1. Лямбды

Лямбда-выражения представляют упрощенную запись анонимных методов. Лямбда-выражения позволяют создать емкие лаконичные методы, которые могут возвращать некоторое значение и которые можно передать в качестве параметров в другие методы.

Ламбда-выражения имеют следующий синтаксис: слева от лямбда-оператора => определяется список параметров, а справа блок выражений, использующий эти параметры: (список_параметров) => выражение. Например:

class Program

{

delegate int Square(int x); // объявляем делегат, принимающий int и возвращающий int

static void Main(string[] args)

{

Square squareInt = i => i * i; // объекту делегата присваивается лямбда-выражение

int z = squareInt(6); // используем делегат

Console.WriteLine(z); // выводит число 36

Console.Read();

}

}

Здесь i => i * i представляет лямбда-выражение, где i - это параметр, а i*i - выражение.

При использовании надо учитывать, что каждый параметр в лямбда-выражении неявно преобразуется в соответствующий параметр делегата, поэтому типы параметров должны быть одинаковыми. Кроме того, количество параметров должно быть таким же, как и у делегата. И возвращаемое значение лямбда-выражений должно быть тем же, что и у делегата.

Возьмем класс Account из прошлой темы и перепишем прикрепление обработчика события с помощью лямбды-выражения:

Account account = new Account(200, 6);

account.Added += (sender, e)=>

{

Console.WriteLine("Сумма транзакции: {0}", e.sum);

Console.WriteLine(e.message);

};

Поскольку здесь используется несколько параметров, то они заключаются в скобки. И так как в теле лямбда-выражения применяется несколько выражений, то они заключаются в блок из фигурных скобок.

Бывает, что параметров не требуется. В этом случае вместо параметра в лямбда-выражении используются пустые скобки:

class Program

{

delegate void message(); // делегат без параметров

static void Main(string[] args)

{

message GetMessage = () => { Console.WriteLine("Лямбда-выражение"); };

GetMessage();

Console.Read();

}

}

Также лямбда-выражение необязательно должно принимать блок операторов и выражений. Оно может также принимать ссылку на метод:

class Program

{

delegate void message(); // делегат без параметров

static void Main(string[] args)

{

message GetMessage = () => Show_Message();

GetMessage();

}

private static void Show_Message()

{

Console.WriteLine("Привет мир!");

}

}

Как и делегаты, лямбда-выражения можно передавать в качестве параметров методу. Нередко лямбды в качестве параметров и используются, что довольно удобно:

class Program

{

delegate bool IsEqual(int x);

static void Main(string[] args)

{

int[] integers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// найдем сумму чисел больше 5

int result1 = Sum(integers, x => x > 5);

Console.WriteLine(result1); // 30

// найдем сумму четных чисел

int result2 = Sum(integers, x => x % 2 == 0);

Console.WriteLine(result2); //20

Console.Read();

}

private static int Sum(int[] numbers, IsEqual func)

{

int result = 0;

foreach (int i in numbers)

{

if (func(i))

result += i;

}

return result;

}

}

Метод Sum принимает в качестве параметра массив чисел и делегат IsFunc и возвращает сумму чисел массива в виде объекта int. В цикле проходим по всем числам и складываем их. Причем складываем только те числа, для которых делегат IsEqual funcвозвращает true. То есть делегат IsEqual здесь фактически задает условие, которому должны соответствовать значения массива. Но на момент написания метода Sum нам неизвестно, что это за условие.

При вызове метода Sum ему передается массив и лямбда-выражение:

int result1 = Sum(integers, x => x > 5);

То есть параметр x здесь будет представлять число, которое передается в делегат:

if (func(i))

А выражение x > 5 представляет условие, которому должно соответствовать число. Если число соответствует этому условию, то лямбда-выражение возвращает true, а переданное число складывается с другими числами.

Подобным образом работает второй вызов метода Sum, только здесь уже идет проверка на числа четность, то есть если остаток от деления на 2 равен нулю:

int result2 = Sum(integers, x => x % 2 == 0);