Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
7 семестр / Учебники / Все лекции С# / Все лекции С# / Лекция 17. Семейства. Индексаторы.doc
Скачиваний:
132
Добавлен:
24.02.2016
Размер:
121.34 Кб
Скачать

Пример с использованием собственного семейства

public abstract class Animal

{

protected string name;

public string Name

{

get

{return name;}

set

{name = value;}

}

public Animal()

{name = "У животного нет имени";}

public Animal(string newName)

{name = newName;}

public void Feed()

{Console.WriteLine("{0} кушает", name);}

}

public class Cow: Animal

{

public void Milk()

{Console.WriteLine("{0} дает молоко", name);}

public Cow(string newName): base(newName)

{}

}

public class Chicken : Animal

{

public void LayEgg()

{

Console.WriteLine("{0} несет яйца", name);

}

public Chicken(string newName): base(newName)

{}

}

public class Animals : CollectionBase//собственное семейство

{

public void Add(Animal newAnimal)

{List.Add(newAnimal);}

public void Remove(Animal oldAnimal)

{

List.Remove(oldAnimal);

}

public Animals()

{

}

public Animal this[int animalIndex]

{

get

{

return (Animal)List[animalIndex];

}

set

{

List[animalIndex] = value;

}

}

}

class Class

{

static void Main(string[] args)

{

Console.WriteLine("Использование семейства для class Animals:");

Animals animalCollection = new Animals();

animalCollection. Add (new Cow ("Новая Буренка"));

animalCollection.Add(new Chicken("Новая Курица"));

foreach (Animal myAnimal in animalCollection)

{

Console.WriteLine("Новый {0} объект добавлен в семейство " + " Name = {1}", myAnimal.ToString(), myAnimal.Name);

}

animalCollection[0].Feed(); //теперь так можно обратиться к элементам семейства

((Cow)animalCollection[0]).Milk();

((Chicken)animalCollection[1]).LayEgg();

}

Семейства с доступом по ключу и интерфейс iDictionary

Кроме интерфейса IList, в семействах можно реализовать аналогичный интерфейс IDictionary, который позволяет осуществлять доступ к элементам по значению ключа (например, по строке с именем) вместо доступа по индексу. Это тоже достигается с помощью индексатора, однако в данном случае параметр индексатора привязывается к хранящемуся элементу, а не к индексу типаint, что позволяет сделать семейство несколько более дружественным по отношению к пользователю. Точно так же, как и для индексируемых семейств, в данном случае имеется базовый класс, который можно использовать для упрощения реализации интерфейса IDictionary— класс DictionaryBase.

Класс DictionaryBase, как и класс ColllectionBase, реализует некоторые (но не все) члены, полученные посредством поддерживаемых им интерфейсов. Так же, как и в классе CollectionBase, в нем реализованы методыClear() иCount(), а вот метод RemoveAt() — нет.. Однако IDictionary обладает методом Remove(), являющимся одним из тех методов, которые необходимо реализовать для создаваемых пользователем классов семейств, основанных на классе DictionaryBase.

Следующий код являет собой пример альтернативной версии класса Animals из предыдущего примера, который на этот раз в качестве базового класса использует класс DictionaryBase. В него входят методы Add(), Remove() и индексатор доступа по ключу:

public class Animals : DictionaryBase

{

public void Add(string newID, Animal newAnimal)

{

Dictionary.Add(newID,newAnimal);

}

public void Remove(string animalID)

{

Dictionary.Remove(animalID);

}

public Animals() {}

public Animal this[string animalID]

{

get {return (Animal)Dictionary[animalID];}

set {Dictionary[animalID]=value;}

}

foreach (DictionaryEntry my in AnimalCollection)

{

Console.WriteLine(“Новый {0} объект добавлен в семейство” + “Name={1}”,my.Value.ToString(), ((Animal)my.Value).Name);

}

В данном примере метод Add() принимает два параметра: ключ и значение, которые будут храниться совместно. Данная реализация предусматривает передачу значения типа string в качестве ключа и передачу объекта типа Animal.

Метод Remove() получает в качестве параметра ключ, а не ссылку на объект. Элемент, обладающий значением, заданным с помощью ключа, удаляется.

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

Еще одним отличием семейств с базовым классом DictionaryBase от семейств с базовым классом CollectionBase является то, что для них немного по-разному выполняется конструкция foreach. Использование конструкции foreach с классом, производным от DictionaryBase приводит к получению типа DictionaryEntry — еще одного типа, описанного в пространстве имен System.Collections. Для того чтобы добраться до самих объектов типа Animal, необходимо воспользоваться членом этой структуры value.