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

Предположим, что вы создали класс КурсВалют, который имеет свойство Доллар. В первой версии класса это свойство просто дает доступ к закрытой переменной доллар. Во второй версии мы решили (не меняя интерфейс пользователя) изменить способ вычисления курса доллара и вместо обращения к переменной доллар, обращаемся к базе данных. В третьей версии класса мы можем вновь изменить тактику вычисления свойства и вместо обращения к базе данных (в ветви get свойства Доллар) обратиться к Web-сервису.

Свойства, даже если они кажутся ненужными, позволяют пользоваться механизмом привязки к данным (DataBinding). Этот мощный механизм (а также инструмент студии на этапе разработки проекта) способен синхронизировать свойства различных объектов, минуя стадию разработки кода реакции на события. Например, вы можете одной строкой кода привязать свойство Text метки формы к свойству Size самой формы и метка будет синхронизирована с размером формы, она будет автоматически отслеживать размер и отображать его в виде текста.

Вставьте в класс Man фрагмент, который объявляет и реализует свойство. Позже мы добавим и другие свойства.

public static SortMode SortBy   // Свойство SortBy типа SortMode

{

      // Вставьте ваш код . . .

}

Для управления статической переменной (sortBy) свойство тоже должно быть статическим. С точки зрения синтаксиса свойство выглядит как структура С++, в которую вложены два метода get и set, которые лучше называть аксессорами (они не тянут на методы по синтаксису, но они превратятся в методы в MSIL-коде). Аксессор get возвращает текущее значение переменной sortBy. Переменную sortBy надо сделать закрытой. Сделайте это.

Внутри аксессора set проверьте легальность того, что пытается выполнить пользователь, и выбросьте одно из стандартных исключений в случае, если он присваивает переменной (точнее, свойству) некорректное значение. При создании исключения используйте форматированный текст (например,

string.Format ("\n\nНеверно задан режим сортировки: {0}\n\n", value);

Для того, чтобы посмотреть как это работает, введите изменения в функцию Main.

   if (Man.SortBy == SortMode.byName) // Иллюстрация работы со свойством. Здесь работает get

  Man.SortBy = SortMode.byAge;      // Здесь работает set

Array.Sort(men);

Console.WriteLine ("\n\nMen after Sort by age:\n");

foreach (Man m in men)

  m.Out();

Man.SortBy = (SortMode)20;       // Здесь мы намеренно вызываем исключение

Этот код надо выполнять по шагам и смотреть, как работает свойство. Сначала происходит сортировка по имени, затем по возрасту, затем появляется диалог, свидетельствующий о возникновении исключения. Так как мы лишь выбрасываем исключение, не обрабатывая его, то система реагирует на него стандартным образом. В сообщении найдите наш текст: "Неверно задан режим сортировки". Он разъясняет реальную причину исключения. В качестве упражнения самостоятельно введите обработку исключения (блоки try и catch). Не следует вводить их внутрь CompareTo, лучше сделайте это в методе TestManArray. Вопрос. Как работает свойство SortBy при выполнении оператора: Man.SortBy++;.

Boxing и Unboxing

Про эти механизмы излишне много пишут, но они должны быть тривиальны для Вас, так как вы знаете, как работает полиморфизм в С++. Покажем оба механизма на примере.

int i = -5;   // Простой тип (value type)

object o = i;   // Сложный тип (reference type).  Эта процедура называется boxing.

Console.WriteLine("o = " + o);

Все типы происходят от object. Вспомните: object (родитель) может показывать на int (ребенка). Здесь важно, что переменная i была в stack, а ее копия (в виде объекта o) перемещается в heap. Копия перекочевала в heap, так как все reference types живут только там. Где-то (незаметно) сработала операция new object. Также важно, что переменная o является ссылкой, живущей в stack. o — это только адрес переменной типа reference, живущей в heap.