Разработка приложений на языке C#. Полезные настройки. Особые спецификаторы формата, страница 23

Вы видели, как работает стандартный одномерный массив переменных произвольного типа и убедились в том, что C# предоставляет дополнительные возможности управления, отсутствующие в C++. Они стали доступны благодаря тому, что по умолчанию все массивы в C# поддержаны классом System.Array. Размер массива в примере был задан заранее (был известен на этапе компиляции). Но C# допускает и другой сценарий, когда размер массива определяется непосредственно в ходе выполнения программы. В этом смысле такой массив можно считать динамической структурой, так как его размер изменяется на этапе выполнения. Например, массив ссылок на объекты класса Man может быть задан так:

Console.Write("\nEnter Man array ");

int size =  Helper.AskInt ("Array size: ", 1, 3); // Запрашиваем желаемый размер массива

Man[] men = new Man[size];       // Отводим память динамически (на этапе выполнения)

for (int i=0; i<size; i++) // Создаем сами объекты, на которые ссылаются элементы массива

{

  men[i] = new Man();

  //==== Здесь можно вставить вызов метода ввода данных —  men[i].In();

  men[i].Out();

}

При создании массива мы можем непосредственно пользоваться услугами класса Array, который позволяет организовать работу с массивом произвольного типа, произвольного ранга (количества измерений) и произвольных размеров вдоль каждого измерения. Например, матрица вещественных чисел, размерностью в n строк и m столбцов может быть создана так.

Console.Write("\nEnter Matrix Dimensions\n");

int n = Helper.AskInt ("Rows: ", 1, 4), // Запрашиваем желаемые размеры матрицы

    m = Helper.AskInt ("Columns: ", 1, 4);

Array a = Array.CreateInstance (typeof(double), n, m); // Массив в n строк и m столбцов

Console.WriteLine ("Rank = {0}", a.Rank);

for (int i = a.GetLowerBound(0);  i <= a.GetUpperBound (0);  i++)

{

  for (int j = a.GetLowerBound(1);  j < a.GetLength(1);  j++)

  {

    a.SetValue (Math.Sin (Math.PI * (i+j)/4), i,j);

    Console.WriteLine("a[{0},{1}] = {2}", i, j, a.GetValue(i,j));

  }

}

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

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

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

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

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

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

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);      // Вставляем ссылку в начало списка