Главная » C# » Применение лямбда-выражений в Visual C# (Sharp)

0

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

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

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

Рис. 9.1. Ячейки электронной таблицы

Наша электронная таблица имеет девять ячеек, три из которых содержат значения. Ячейки А2 и Bi содержат значения, а ячейка сз — формулу, которая суммирует знения  первых двух ячеек.  Результаты  ячейки  сз  умножаются  на 2  и  помещаются в ячейку С2. Все это стандартные операции с электронной таблицей. Теперь рамотрим исходный код для выполнения вычислений в таблице. Подумайте немно, как это сделать, прежде чем продолжать читать дальше.

Создание алгоритма

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

interface ICell { void Execute();

}

Метод Execute о можно рассматривать как "волшебный", т. к. он сам знает, что делать с ячейкой. Тогда всю таблицу можно представить следующей коллекцией:

IListcIListcICell» spreadsheet;

Коллекция внутри объявления коллекции создает двумерный список ячеек. Данное объявление является примером электронной таблицы с динамическими размерами. Для сравнения, рассмотрим следующее объявление массива электронной таблицы постоянных размеров:

ICell[,]  spreadsheet;

Как видим, электронную таблицу можно объявить несколькими способами. Для данного примера мы будем пользоваться таблицей, объявленной как коллекция коллекций.

Для  обработки  таблицы  создается  цикл  foreach, в  котором  исполняется  метод

ICell.Execute():

foreach (IList<ICell> rows in spreadsheet) { foreach (ICell cell in rows) {

cell.Executed ;

}

}

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

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

Реализация алгоритма с помощью лямбда-выражения

Другим подходом к организации электронной таблицы будет использование лямбда-выражений. Рассмотрим следующее объявление электронной таблицы:

class Spreadsheet {

public Func<object>[,] Cells;

public object!,] State;

public Spreadsheet() {

Cells = new Func<object>[10, 10]; State = new objecttlO, 10];

public void Execute() {

for (int col = 0; col < Cells.GetLength(l); col++) { for (int row = 0; row < Cells.GetLength(O); row++) {

if (Cells[col, row] != null) { State[col, row] = Cellsfcol, row]();

}

}

}

}

Данная таблица имеет два члена данных — cell s и state . Член данных  Cell s  яяется двумерным массивом лямбда-выражений, возвращающих объект. Каждое лямбда-выражение будет содержать какой-то исполняемый код. Член данных stat e содержит  результаты  исполнения  и  предоставляется  пользователю.

Значения  ячейкам  присваиваются  с  помощью  следующего  кода:

static class CellFactories {

public static Func<object>DoAdd(Func<object> celll,

Func<object>cell2){ return () => (double)celll() + (double)cell2();

}

public static Func<object> DoMultiply(Func<object> celll,

Func<object> cell2) { return () => (double)celll() * (double!cell2();

}

public static Func<object> Static(object value) { return () => value;

}

}

Клас с CellFactories Содержит три  метода:  DoAdd(), DoMultiply() И Static о, корые суммируют, умножают и вычисляют статическое значение в определенной ячейке соответственно. Рассмотрим реализацию метода DoAdd (). Здесь лямбдыражение  использует  два  других  лямбда-выражения,  чтобы   получить   значения для  вычисления  результата сложения.

Последовательность исполняемых операций определяется структурой лямбдыражений. Это означает,  что если  первыми запрашиваются результаты для ячейки С2,

то выполняется обращение и обработка ячейки сз, в результате которой извлекаются значения ячеек А2 И BI. Таким образом, устраняется возможность неправильного висления ячеек. Код для обработки электронной таблицы, показанной на рис. 9.1, выглядит таким образом:

Spreadsheet spreadsheet = new Spreadsheet();

spreadsheet.Cells[1,0] = CellFactories.Static(10.0); spreadsheet.Cells[0,1] = CellFactories.Static(10.0); spreadsheet.Cells[1,2] =

CellFactories.DoAdd(spreadsheet.Cells[1,0],  spreadsheet.Cells[0,1]); spreadsheet.Cells[2,2] =

CellFactories.DoMultiply(spreadsheet.Cells[1,2],

CellFactories.Static(2.0));

spreadsheet.Execute();

В  данном  коде,  с  помощью  фабрик  инициализируются  базовые  значения   ю. о и ю.о . Обратите внимание на формат значений: ю.о , а не просто ю. Отсутствие десятичной точки и нуля вызвало бы ошибку преобразования типов. Потом выпояется операция присваивания значения ячейке cell[1,2], для  чего  вызывается мето д DoAdd() С ячейкам и Cells [1, 0] и Cells [0,1].

Источник: Гросс  К. С# 2008:  Пер. с англ. — СПб.:  БХВ-Петербург, 2009. — 576 е.:  ил. — (Самоучитель)

По теме:

  • Комментарии