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

Такое поведение static-данных вполне отвечает нашим интересам. Осталось решить, надо ли помещать наши функции в один из существующих классов Man (ManTest), или в какой-то новый класс. В процессе выработки решения следует задать вопрос, является ли функция надежного ввода неотъемлемой частью класса Man? Очевидным ответом будет — нет. Надежный ввод может понадобиться и другим компонентам. Поэтому целесообразно создать вспомогательный класс (назовем его Helper), который будет содержать набор служебных public static-функций. Создайте класс с помощью студии. Он должен быть в другом файле, но в том же пространстве имен MyConsole.

public class Helper

{ //========= Запрос на ввод целого числа

public static int AskInt (string prompt,/* Текст подсказки*/ int min, int max /* Ограничения*/ )

{

  int res = min - 1; // Пессимистический прогноз

  for (bool ok = false; !ok; ) // Приставучий цикл

  {

    Console.Write (prompt);

    ok = MakeInt (Console.ReadLine(), min, max, out res); // Вызов второй утилиты

  }

  return res;

}

public static bool MakeInt (string s, int min, int max, out int res)

{

  bool ok = true;  // Оптимистический прогноз

  res = min - 1;   // Пессимистический прогноз

  try // Попытка выполнить ненадежный код

  {

    res = int.Parse (s); // Эта функция может выдать исключение

    ok = min <= res && res <= max;

    if (!ok)

      Console.WriteLine ("Value must be in ({0}, {1})", min, max);

  }

  catch // Ловим все типы исключений

  {

    Console.WriteLine ("It is not valid integer");

    ok = false;

  }

  return ok;

}

}

Проверьте работу статических методов класса Helper, изменив тело метода In в классе Man.

age = Helper.AskInt("Age: ", 0, 100);

При проверке попытайтесь ввести недопустимые символы или выйти из диапазона (0, 100).

Массивы объектов

Ранг одномерного массива имеет значение 1, двухмерного — 2 и т. д. Каждое измерение массива имеет свой размер (Length). Оба эти параметра могут быть получены с помощью механизма свойств, который мы вскоре рассмотрим более подробно. Уберите из метода TestMan тривиальный код и добавьте новый, в котором мы исследуем работу с массивом объектов.

Man[] men =  // Объявляем массив ссылок на объекты класса Man

{

  new Man ("Sam Lamb",32),

  new Man ("Graham Dumb",12),

  new Man ("Alan Calm",52)

};

foreach (Man m in men)       // Один из 4-х типов циклов в С#

  m.Out();

   Console.WriteLine ("\nArray Rank = {0} ",men.Rank); // Хотим увидеть фундаментальные свойства

Console.WriteLine ("Array Length = {0} ",men.Length);

Массив ссылок на объекты класса Man (по сути это адреса) объявлен, инициализирован и выведен с помощью цикла foreach. Здесь полезно нарисовать структуру данных и связи (указатели, точнее ссылки). Одна ссылка в стеке, три ссылки в области heap, и три объекта там же. На самом деле имена людей (объекты класса string) расположены в других местах, объекты класса Man содержат лишь ссылки на эти места.

При выводе автоматически срабатывает переопределенный вами метод ToString(). Если бы не местоположение квадратных скобок, то объявление массива могло бы сойти за объявление на С++. Но главным отличием от С++ здесь все же является не местоположение скобок, а тот факт, что с их помощью мы декларируем массив адресов (читай, ссылок) на объекты класса Man, а не массив самих объектов, как это было бы в С++. Аналогом подобной структуры в С++ будет объявление массива адресов, а не массива объектов. Приведем этот аналог.

Man** men = { new Man("Sam Lamb",32), new Man ("Graham Dumb",12), new Man ("Alan Calm",52) };

В языке C# существующий массив можно переопределить, например, так:

men = new Man[2];

Console.WriteLine ("Array Length = {0} ", men.Length);