Исследование MS Visual С#, страница 14

  }

}

Заголовки циклов немного отличаются. Это сделано намеренно — чтобы показать возможности. Мы создали массив переменных типа value type, если вы помните, что это означает. Для создания массива элементов типа Man (reference type) надо поступить по-другому. Как? Например, так.

Array a = Array.CreateInstance (typeof(Man), n, m);

Но при этом был бы создан принципиально, то есть качественно, другой массив. Это был бы массив ссылок (references) на объекты класса Man. При инициализации элементов такого массива что-то надо делать по-другому. Что и как? Сделайте это.

Динамические коллекции объектов

На практике, однако, значительно чаще возникает необходимость работать с «настоящими» динамическими структурами данных, то есть такими, размер которых может изменяться в процессе выполнения как в сторону увеличения, так и в сторону уменьшения.

Рассмотрим класс ArrayList пространства имен Collections. Давайте создадим динамическую структуру данных для хранения объектов класса Man на основе класса ArrayList. Управляя такой структурой, мы ближе познакомимся с его свойствами и методами. Не забудьте сделать доступным пространство имен Collections. Затем измените тело главной функции.

static void Main()

{

// Создайте ссылки на отдельные объекты класса

ArrayList men = new ArrayList(); // Создаем коллекцию ссылок на объекты

  Console.WriteLine("List properties:\n"+

  "\nCapacity:       {0}\nIsFixedSize:    {1}"+

  "\nIsReadOnly:     {2}\nIsSynchronized: {3}",

  men.Capacity, men.IsFixedSize,

  men.IsReadOnly, men.IsSynchronized);

  men.Add(ken);   men.Add(ben);    men.Add(len); // Вставляем ссылки в конец списка

men.Sort();     // Сравните этот вызов с тем, который был ранее

Console.WriteLine("Men after Sort by name:\n");

foreach (Man m in men)

  m.Out();

men.Add(ken);      // Добавляем ссылку в конец списка

men.Insert (0,ken);   // Вставляем ссылку в начало списка

ArrayList other = (ArrayList)men.Clone(); // Создаем клон списка

Console.WriteLine("\nMen Clone:\n");

foreach (Man m in other)

  m.Out();

}

Попробуйте изменить оригинал и после этого проверить копию (клон). Какой тип копирования был использован по умолчанию?

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

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

static void Main()

{

Man

  ken = new Man("Ken Wood",40),

  len = new Man("Lennie Tristano",50),

  ben = new Man("Ben Webster",60);

Man[] ma = { ken, len, ben };

ArrayList men = new ArrayList(ma); // Создаем коллекцию на основе массива

ma = new Man[] { ken, ken, ken, ken };// Массив меняет все свои элементы

int id = men.LastIndexOf (ben);// Узнаем где (в коллекции) сидит Ben Webster

men.InsertRange (id, ma);      // Вставляем перед ней стандартный массив

men.InsertRange (id, ma);      // Повторяем вставку (для убедительности)

Console.WriteLine("\nMen after ken's attack:\n");

foreach (Man m in men)

  m.Out();

}

Задание: Продолжите эту тему (в коллекции много Ken'ов) и реализуйте такой алгоритм.

1.  Удалите первую ссылку на Ken Wood. Используйте метод Remove.

2.  Найдите позицию следующего Ken’а (IndexOf) и удалите объект с помощью метода RemoveAt.

3.  Вычислите, сколько объектов расположено в коллекции после текущей позиции. Присвойте это значение переменной nLeft и выведите на экран.

4.  Возродите стандартный массив ma так, чтобы его размер стал nLeft.

5.  Скопируйте последние nLeft элементов коллекции в массив ma. Используйте метод CopyTo.

6.  Проверьте, что получилось.

7.  Удалите из коллекции всех оставшихся Ken’ов (методы Contains и Remove) и проверьте.

8.  Скопируйте все элементы коллекции в стандартный массив с помощью метода ToArray класса ArrayList.

Кроме методов, объявленных в родительских интерфейсах, класс ArrayList обладает рядом своих собственных, среди которых несколько необычным кажется метод ToArray, который копирует все элементы коллекции в массив. Отметьте, что при этом нет необходимости предварительно узнавать размер последовательности и выделять соответствующую память для массива-мишени. Сравните эту технологию с той, которая используется при вызове метода CopyTo. Последний требует, чтобы массив (мишень копирования) не только существовал, но и имел достаточный размер.

Метод ToArray имеет две версии. Первую вы, вероятно, использовали в примере, а вторая отличается тем, что возвращает массив ссылок типа object. Фрагмент создания и копирования массива в этом случае имеет такой вид:

object[] mo = men.ToArray();    // Такой синтаксис выглядит очень мощно

Console.WriteLine ("\nArray copy of men:\n");

foreach (Man m in mo)

m.Out();

((Man)mo[0]).In();     // Изменяем копию

string s = men[0].ToString(); // Проверяем оригинал. Он изменился.

При анализе кода постарайтесь понять следующее: как массив object[] mo, так и коллекция ArrayList men, хранят ссылки типа object, а не ссылки типа Man. Поэтому при их использовании для вызова методов класса Man следует пользоваться операцией явного приведения типа. Например: ((Man)mo[0]).In();. Какой тип копирования происходит в этом примере? Запустив фрагмент в режиме отладки (F10), вы сможете собственными глазами увидеть все, что происходит.