Ћекции.ќрг


ѕоиск:




 атегории:

јстрономи€
Ѕиологи€
√еографи€
ƒругие €зыки
»нтернет
»нформатика
»стори€
 ультура
Ћитература
Ћогика
ћатематика
ћедицина
ћеханика
ќхрана труда
ѕедагогика
ѕолитика
ѕраво
ѕсихологи€
–елиги€
–иторика
—оциологи€
—порт
—троительство
“ехнологи€
“ранспорт
‘изика
‘илософи€
‘инансы
’ими€
Ёкологи€
Ёкономика
Ёлектроника

 

 

 

 


»спользование стандартного интерфейса IEnumerable




 

Ќа первый взгл€д преимуществ во введении интерфейсного класса нет Ц методы кодировани€ и декодировани€ можно разместить непосредственно в классе MyzikText.

–еально существующие в библиотеке платформы .NET классы включают большое число интерфейсных методов различных интерфейсов, наследу€ которые, классы получают дополнительные свойства Ц через название методов, а не через их реализацию. –еализацию интерфейсных методов каждый интерфейсный класс, как правило, должен выполн€ть самосто€тельно. Ќапример, если в нашем классе необходимо организовать просмотр с помощью цикла foreach некоторых перечисл€емых объектов представленных массивом, то наш класс должен быть наследником интерфейса IEnumerable (перечислимый). ” этого интерфейса всего один метод GetEnumerator(), возвращающий объект типа Enumerator (перечислитель). ‘ормат записи метода GetEnumerator() имеет следующий вид:

IEnumerator GetEnumerator();

“аким образом, наш класс должен быть наследником интерфейсов IEnumerable и IEnumerator.

»нтерфейса IEnumerator включает одно свойство Object Current{get;}, возвращающее очередной перечисл€емый объект, и два метода Ц bool MoveNext(), передвигающий перечислитель на следующий перечисл€емый объект, и метод void Reset(), устанавливающий перечислитель на первый перечисл€емый объект.

¬ совокупности именно указанное свойство и эти два метода позвол€ют организовать процесс просмотра объектов массивов с помощью цикла foreach. ћетоды этих интерфейсов работают с виртуальной коллекцией (набором объектов определ€емых в процессе работы программы), что и определ€ет их универсальность.

≈сли в классе необходимо выполн€ть сравнение объектов, например, при их сортировке, то такой класс следует объ€вить наследником интерфейса IComparable. Ётот интерфейс имеет всего один метод CompareTo(object obj), возвращающий целочисленное значение, положительное, отрицательное или равное нулю, в зависимости от выполнени€ отношени€ "больше", "меньше" или "равно".

–ассмотрим работу с интерфейсами IEnumerable и IEnumerator на учебном примере, в котором необходимо организовать просмотр товаров некоторого магазина. ƒл€ простоты считаем, что класс Tovar имеет два пол€ название товара и его цена.

class Tovar

{

public string Naz; // Ќазвание и цена товара

public int Cena;

public Tovar(string n, int c) //  онструкор товара

{

Naz = n;

Cena = c;

}

}

ƒл€ хранени€ объектов типа Tovar используем класс Cklad, имеющий следующую структуру:

class Cklad

{

public Tovar[] tovar; // ћассив товаров

public Cklad() //  онструктор склада

{

tovar = new Tovar[4];

}

}

ћаксимальное количество объектов, которое может хранитьс€ на складе, в учебных цел€х прин€то равным 4.

–ассмотрим работу программы без использовани€ интерфейса IEnumerable.

 од программы:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

public partial class Form1: Form

{

public static string s;

public static int kol;

class Tovar

{

public string Naz; // Ќазвание и цена товара

public int Cena;

public Tovar(string n, int c) //  онструкор товара

{

Naz = n;

Cena = c;

}

}

class Cklad

{

public Tovar[] tovar; // ћассив товаров

public Cklad() //  онструктор склада

{

tovar = new Tovar[4];

}

}

public Form1()

{

InitializeComponent();

kol = 0;

s = "";

}

Cklad ckl = new Cklad();

 

private void button2_Click(object sender, EventArgs e)

{

if (kol < 4)

{

ckl.tovar[kol] = new Tovar(textBox1.Text, Convert.ToInt32(textBox2.Text));

s = s + textBox1.Text + textBox2.Text + "\r\n";

}

else { s = s + "CKLAD POLHIJ" + "\r\n"; kol--; }

kol++;

textBox3.Text = s;

}

private void button1_Click(object sender, EventArgs e)

{

s = "";

s = "–аботает цикл foreach"+ "\r\n";

foreach (Tovar t in ckl.tovar)

{

s = s + t.Naz + " " + t.Cena.ToString() + "\r\n";

}

s = s + "–аботает цикл for" + "\r\n";

for (int i = 0; i < kol; i++)

{

s = s + ckl.tovar[i].Naz + " " + ckl.tovar[i].Cena.ToString() + "\r\n";

}

textBox3.Text = s;

}

}

}

–абота программы

 

–исунок 11.2 Ц –абота программы без интерфейсов

 

Ќеобходимо отметить, что в программе цикл foreach используетс€ только дл€ переменной типа массив ckl.tovar, который уже имеет встроенный интерфейс Ц все классы массивы, независимо от типа элементов, реализуют перечисление элементов массива, и дл€ них определен метод GetEnumerator.

ќднако, если мы попытаемс€ использовать цикл foreach дл€ объектов класса Tovar в объекте ckl типа Cklad, а не дл€ массива tovar объекта класса Cklad, например,

foreach (Tovar t in ckl)

{

s = s + t.Naz + " " + t.Cena.ToString() + "\r\n";

}

то программа выдаст сообщение об ошибке:

 

Ђforeach statement cannot operate on variables of type ' WindowsFormsApplication1.Form1.Cklad ' because 'Books' does not contain a public definition for 'GetEnumerator'ї

(ќператор foreach не может примен€тьс€ к переменным типа ' WindowsFormsApplication1.Form1.Cklad ', так как переменные этого класса не содержат открытого определени€ метода ' GetEnumerator').

ƒоопределим нашу программу необходимым интерфейсом, дл€ этого в нашей программе необходимо добавить дополнительное пространство имен:

using System.Collections;

 ласс Cklad должен наследовать интерфейс IEnumerable:

class Cklad: IEnumerable

¬ тело класса Cklad необходимо включить реализацию метода GetEnumerator:

public IEnumerator GetEnumerator()

{

for (int i = 0; i < 4; i++) yield return tovar[i];

}

Ќеобходимы некоторые комментарии, которые вз€ты из книги “.ј.ѕавловской (стр. 207.)

Ђ“аким образом, если требуетс€, чтобы дл€ перебора элементов класса мог примен€тьс€ цикл foreach, необходимо реализовать четыре метода: GetEnumerator, Current, MoveNext и Reset. Ќапример, если внутренние элементы класса организованы в массив, потребуетс€ описать закрытое поле класса, хран€щее текущий индекс в массиве, в методе MoveNext задавать изменение этого индекса на 1 с проверкой выхода за границу массива, в методе Current Ц возврат элемента массива по текущему индексу и т.д.

Ёто не интересна€ работа, а выполн€ть ее приходитс€ часто, поэтому в версии 2.0 были введены средства, облегчающие выполнение перебора в объекте Ц итераторы.

»тератор представл€ет собой блок кода, задающий последовательность перебора элементов объекта. Ќа каждом проходе цикла foreach выполн€етс€ один шаг итератора, заканчивающийс€ выдачей очередного значени€. ¬ыдача значени€ выполн€етс€ с помощью ключевого слова yield.

...

¬се, что требуетс€ сделать в версии 2.0 дл€ поддержки перебора Ч указать, что класс реализует интерфейс IEnumerable, и описать итератор. ƒоступ к нему может быть осуществлен через методы MoveNext и Current интерфейса IEnumerator. «а кодом, приведенным в листинге итератора, стоит больша€ внутренн€€ работа компил€тора.

Ќа каждом шаге цикла foreach дл€ итератора создаетс€ Ђоболочкаї Ч служебный объект, который запоминает текущее состо€ние итератора и выполн€ет все необходимое дл€ доступа к просматриваемым элементам объекта. »ными словами, код, составл€ющий итератор, не выполн€етс€ так, как он выгл€дит Ч в виде непрерывной последовательности, а разбит на отдельные итерации, между которыми состо€ние итератора сохран€етс€.ї.

ѕриведенные два небольших изменени€ в программе позвол€ют использовать цикл foreach, который ранее выдавал сообщение об ошибке.

Ќеобходимо отметить особенность работы цикла foreach, котора€ может приводить к Ђзависаниюї программ. ≈сли в нашей программе, после ввода нескольких объектов товара, но не до полного заполнени€ массива, мы включим режим просмотра товаров на складе, то программа Ђповиснетї при попытке вывода несуществующих значений Ц необходимо контролировать Ђперебираемыеї значени€ цикла foreach.

÷икл for не имеет этих недостатков, потому что его конечное значение определ€етс€ текущим значением глобальной переменной kol.

for (int i = 0; i < kol; i++)

{

s = s + ckl.tovar[i].Naz + " " + ckl.tovar[i].Cena.ToString() + "\r\n";

}

 





ѕоделитьс€ с друзь€ми:


ƒата добавлени€: 2015-05-05; ћы поможем в написании ваших работ!; просмотров: 524 | Ќарушение авторских прав


ѕоиск на сайте:

Ћучшие изречени€:

Ћюди избавились бы от половины своих непри€тностей, если бы договорились о значении слов. © –ене ƒекарт
==> читать все изречени€...

759 - | 606 -


© 2015-2023 lektsii.org -  онтакты - ѕоследнее добавление

√ен: 0.024 с.