Рейтинговые книги
Читем онлайн C# 4.0: полное руководство - Герберт Шилдт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 127 128 129 130 131 132 133 134 135 ... 294

count => count + 2

В этом выражении count служит параметром, на который воздействует выражение count + 2. В итоге значение параметра count увеличивается на 2. А вот еще один пример одиночного лямбда-выражения.

n => n % 2 == 0

В данном случае выражение возвращает логическое значение true, если числовое значение параметра n оказывается четным, а иначе — логическое значение false.

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

В приведенном ниже примере программы демонстрируется применение двух одиночных лямбда-выражений. Сначала в этой программе объявляются два типа делегатов. Первый из них, Incr, принимает аргумент типа int и возвращает результат того же типа. Второй делегат, IsEven, также принимает аргумент типа int, но возвращает результат типа bool. Затем экземплярам этих делегатов присваиваются одиночные лямбда-выражения. И наконец, лямбда-выражения вычисляются с помощью соответствующих экземпляров делегатов.

// Применить два одиночных лямбда-выражения.

using System;

// Объявить делегат, принимающий аргумент типа int и

// возвращающий результат типа int.

delegate int Incr(int v);

// Объявить делегат, принимающий аргумент типа int и

// возвращающий результат типа bool,

delegate bool IsEven(int v);

class SimpleLambdaDemo {

  static void Main() {

    // Создать делегат Incr, ссылающийся на лямбда-выражение,

    // увеличивающее свой параметр на 2.

    Incr incr = count => count + 2;

    // А теперь использовать лямбда-выражение incr.

    Console.WriteLine("Использование лямбда-выражения incr: ");

    int x = -10;

    while(x <= 0) {

      Console.Write(x + " ");

      x = incr(x); // увеличить значение x на 2

    }

    Console.WriteLine ("n");

    // Создать экземпляр делегата IsEven, ссылающийся на лямбда-выражение,

    // возвращающее логическое значение true, если его параметр имеет четное

    // значение, а иначе — логическое значение false.

    IsEven isEven = n => n % 2 == 0;

    // А теперь использовать лямбда-выражение isEven.

    Console.WriteLine("Использование лямбда-выражения isEven: ");

    for (int i=1; i <= 10; i++)

      if(isEven (i)) Console.WriteLine(i + " четное.");

  }

}

Вот к какому результату приводит выполнение этой программы.

Использование лямбда-выражения incr:

-10 -8 -6 -4 -2 0

Использование лямбда-выражения isEven:

2 четное.

4 четное.

6 четное.

8 четное.

10 четное.

Обратите в данной программе особое внимание на следующие строки объявлений.

Incr incr = count => count +2;

IsEven isEven = n => n % 2 == 0;

В первой строке объявления экземпляру делегата incr присваивается одиночное лямбда-выражение, возвращающее результат увеличения на 2 значения параметра count. Это выражение может быть присвоено делегату Incr, поскольку оно совместимо с объявлением данного делегата. Аргумент, указываемый при обращении к экземпляру делегата incr, передается параметру count, который и возвращает результат вычисления лямбда-выражения. Во второй строке объявления делегату isEven присваивается выражение, возвращающее логическое значение true, если передаваемый ему аргумент оказывается четным, а иначе — логическое значение false. Следовательно, это лямбда-выражение совместимо с объявлением делегата IsEven.

В связи со всем изложенным выше возникает резонный вопрос: каким образом компилятору становится известно о типе данных, используемых в лямбда-выражении, например, о типе int параметра count в лямбда-выражении, присваиваемом экземпляру делегата incr? Ответить на этот вопрос можно так: компилятор делает заключение о типе параметра и типе результата вычисления выражения по типу делегата. Следовательно, параметры и возвращаемое значение лямбда-выражения должны быть совместимы по типу с параметрами и возвращаемым значением делегата.

Несмотря на всю полезность логического заключения о типе данных, в некоторых случаях приходится явно указывать тип параметра лямбда-выражения. Для этого достаточно ввести конкретное название типа данных. В качестве примера ниже приведен другой способ объявления экземпляра делегата incr.

Incr incr = (int count) => count + 2;

Как видите, count теперь явно объявлен как параметр типа int. Обратите также внимание на использование скобок. Теперь они необходимы. (Скобки могут быть опущены только в том случае, если задается лишь один параметр, а его тип явно не указывается.)

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

(low, high, val) => val >= low && val <= high;

А вот как объявляется тип делегата, совместимого с этим лямбда-выражением.

delegate bool InRange(int lower, int upper, int v);

Следовательно, экземпляр делегата InRange может быть создан следующим образом.

InRange rangeOK = (low, high, val) => val >= low && val <= high;

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

if(rangeOK(1, 5, 3)) Console.WriteLine(

            "Число 3 находится в пределах от 1 до 5.");

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

Блочные лямбда-выражения

Как упоминалось выше, существуют две разновидности лямбда-выражений. Первая из них, одиночное лямбда-выражение, была рассмотрена в предыдущем разделе. Тело такого лямбда-выражения состоит только из одного выражения. Второй разновидностью является блочное лямбда-выражение. Для такого лямбда-выражения характерны расширенные возможности выполнения различных операций, поскольку в его теле допускается указывать несколько операторов. Например, в блочном лямбда-выражении можно использовать циклы и условные операторы if, объявлять переменные и т.д. Создать блочное лямбда-выражение нетрудно. Для этого достаточно заключить тело выражения в фигурные скобки. Помимо возможности использовать несколько операторов, в остальном блочное лямбда-выражение, практически ничем не отличается от только что рассмотренного одиночного лямбда-выражения.

Ниже приведен пример использования блочного лямбда-выражения для вычисления и возврата факториала целого значения.

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

using System;

// Делегат IntOp принимает один аргумент типа int

// и возвращает результат типа int.

delegate int IntOp(int end);

class StatementLambdaDemo {

  static void Main() {

    // Блочное лямбда-выражение возвращает факториал

    // передаваемого ему значения.

    IntOp fact = n => {

      int r = 1;

      for (int i=1; i <= n; i++)

        r = i * r;

      return r;

1 ... 127 128 129 130 131 132 133 134 135 ... 294
На этой странице вы можете бесплатно читать книгу C# 4.0: полное руководство - Герберт Шилдт бесплатно.
Похожие на C# 4.0: полное руководство - Герберт Шилдт книги

Оставить комментарий