Главная » C# » Верен ли код C# (колекции объектов)?

0

Начнем  рассмотрение  проблем  с  коллекциями  с  широко  распространенной  прлемы: добавление всех элементов в коллекции. Рассмотрим следующий код: IList<int> elements = new List<int>();

elements.Add(1); elements.Add(2); elements.Add(3);

int runningTotal = 0;

foreach (int value in elements) { runningTotal += value;

}

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

вычисления  суммы  необходимо  найти  максимальное значение.  Такой  код  может выглядеть следующим образом:

IList<int> elements = new List<int>();

elements.Add(l); elements.Add(2); elements.Add(3);

int martValue = int.MinValue;

foreach (int value in elements) {

if (value > manValue) { martValue = value;

}

}

Разница между двумя фрагментами кода выделена жирным шрифтом. Инициализия выполняется по-другому, и это нормально. Но цикл также организован пругому, и это уже не нормально. В отдельных фрагментах кода повторение не очевидно, но что если мы сложим их вместе? В следующем коде вычисляется суа всех элементов и находится наибольшее значение:

IList<int> elements = new List<int>(); elements.Add(1);

elements.Add(2); elements.Add(3);

int ruimingTotal =0 ;

foreach (int value in elements) {

runningTotal += value;

}

Console.WriteLine("RunningTotal (" + runningTotal + ")");

int makValue = int.MinValue;

foreach (int value in elements) {

if (value > martValue) { martValue = value;

}

}

Console.WriteLine("Maximum value is (" + maxValue + ")");

Другой вариант может быть таким: IList<int> elements = new List<int>(); elements.Add(1);

elements.Add(2);

elements.Add(3);

int runningTotal =0 ;

int makValue = int.MinValue;

foreach (int value in elements) {

if (value > maXValue) { maatValue = value;

}

runningTotal += value;

}

}

Независимо от используемого варианта,  проблема решается методом  копирования и вставки. Для одного или двух экземпляров написать цикл foreach не так и слоо, но если бы нам потребовалось использовать код итератора в десятке-полтора мест, это уже бы было проблематичным. Такой тип кода труднее поддается сопрождению и расширению. Одним из способов повышения эффективности было бы поместить код в абстрактный базовый класс, реализованный для вычисления почной общей суммы или нахождения максимального значения. Далее привидится пример исходного кода трех таких абстрактных базовых классов: IteratorBaseClass.cs, RunningTotal.cs и MaximumValue.cs. Для тестирования каждый из этих классов можно поместить в отдельный файл,

abstract class IteratorBaseClass { IList<int> Collection;

protected IteratorBaseClass(IList<int> collection) { Collection = collection;

}

protected abstract void ProcessElement(int value); public IteratorBaseClass Iterate() {

foreach (int element in Collection) { ProcessElement(element);

}

return this;

}

}

class RunningTotal : IteratorBaseClass { public int Total;

public RunningTotal(IList<int> collection) : base(collection) { Total = 0;

}

protected override void ProcessElement(int value) { Total += value;

}

class MaximumValue : IteratorBaseClass { public int MaxValue;

public MaximumValue(IList<int> collection) : base(collection) { MaxValue = int.MinValue;

}

protected override void ProcessElement(int value) { if (value > MaxValue) {

MaxValue = value;

}

}

}

static void Main(string[] args)

{

lList<int> elements = new List<int>(); elements.Add(1);

elemants.Add(2); elements.Add(3);

Console.WriteLine("RunningTotal (" +

((new RunningTotal(elements).lterate()) as RunningTotal).Total + ") Maximum Value (" +

((new MaximumValue (elements) .Iterated ) as MaximumValue) .MastValue + ")");

}

Модифицированный код намного длиннее, хотя пользовательский  код  (выделеый жирным шрифтом) — намного короче. Тем не менее, и этот код все еще нравильный. Неправильность его состоит в том, что проблему, решаемую в нем, можно решить другим, более простым, способом. Так что, в общем, можно сказать, что задача состоит в том, что мы хотим решить отдельную определенную техничкую проблему, используя для этого элегантный код, который не содержит скопованные и вставленные повторяющиеся фрагменты. Решение данной задачи с пощью  делегатов,  анонимных  делегатов  и  лямбда-выражений   рассматривается в следующих разделах. Идея заключается в том, чтобы показать практический прер, в котором каждая возможность применяется натуральным образом.

ОЦЕНКА      ПРЕИМУЩЕСТВ      ПОВТОРНОГО     ИСПОЛЬЗОВАНИЯ     КОДА

Очень часто код, который выполнят задачу прямым образом, более короткий и более прямолинейный. Когда же мы начинаем абстрагировать код и разрабатывать общие классы, его объем начинает увеличиваться, что является платой за возможность пторного использования данного кода. Так когда же абстрагирование кода стоит зраченных на  это усилий?

Попробуем ответить на этот вопрос аналогией с постройкой дома. Допустим, что вы строите сами себе дом и вам требуется 50 стропил. Стропила можно  собрать двумя способами: укладывая и соединяя индивидуально их компоненты для  каждого  стрила, или же можно соорудить специальный удерживающий шаблон  для  точной  уадки и соединения компонентов. Проблема заключается в том, какой из этих двух способов  выбрать.  Если  сборка  стропил  без  шаблона  займет  3  дня,  а  с  шаблоном 1 день, то вроде бы стоит собирать стропила с помощью шаблона. Но не все так прто, как кажется. Что если сборка самого шаблона требует 3  дня?  В  таком  случае, время, сэкономленное применением  шаблона,  будет утрачено  на  создание  шаблона. Но если вы строите несколько домов с одинаковыми стропилами, то тогда создание шаблона для  их сборки будет оправдано.

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

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

По теме:

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