netlib.narod.ru | < Назад | Оглавление | Далее > |
Как вы уже знаете, в классах С# могут присутствовать члены, содержащие данные, называемые полями, и члены, содержащие код, — методы. Кроме того, в классах С# может быть еще один вид членов, содержащих код. Эти члены называются свойствами и играют крайне важную роль в .NET Framework.
Свойства как бы размывают различия между кодом и данными. Для использующих класс программ свойства выглядят как поля с данными и часто именно так и рассматриваются. Однако внутри класса свойства, конечно же, являются кодом. Во многих программах открытое свойство обеспечивает другим классам доступ к закрытому полю класса. Свойство имеет преимущество перед полем, так как в него можно поместить проверку допустимости значения.
Некоторые программисты на С# (в том числе и я) дают закрытым полям имена, начинающиеся со строчных букв, а открытым свойствам — имена, начинающиеся с заглавных букв. Ниже приведено простейшее определение свойства Month обеспечивающего доступ к закрытому полю month:
public int Month { set { month = value; } get { return month; } }
Программа, использующая класс с таким свойством, обращается к свойству точно так же, как если бы это было поле:
mydate.Month = 7;
или:
Console.WriteLine(mydate.Month);
или:
mydate.Month += 2;
В последнем примере значение Month увеличивается на 2. Смотрите, насколько синтаксис этого оператора прозрачнее, чем синтаксис аналогичного оператора, использующего методы SetMonth и GetMonth, с которыми мы работали ранее:
mydate.SetMonth(mydate.GetMonth() + 2); // Хорошо, что мы от этого // избавились!
Рассмотрим определение этого свойства подробно. Ключевое слово public означает, что это свойство доступно вне класса. Тип данных int — что свойство является 32-битным целым. Само свойство имеет имя Month.
Внутри тела свойства содержатся два метода доступа (accessors) — set и get. He обязательно использовать оба. У многих свойств есть только открытый метод доступа get, a set или вообще не определен, или определен как private. Такие свойства называются неизменяемыми (read-only). Можно также создать свойство с методом доступа set и без метода доступа get, но это требуется гораздо реже.
Внутри определения метода доступа set специальное слово value служит для указания значения, присваиваемого свойству инструкцией:
mydate.Month = 7;
Метод доступа get всегда должен содержать инструкцию return, чтобы вернуть значение программе, использующей свойство.
Следующая программа использует свойства Year, Month и Day и выполняет в методах доступа set проверку допустимости значений.
CsDateProperties.cs
//-------------------------------------------------- // CsDateProperties.cs (C) 2001 by Charles Petzold //-------------------------------------------------- using System; class CsDateProperties { public static void Main() { Date mydate = new Date(); try { mydate.Month = 8; mydate.Day = 29; mydate.Year = 2001; Console.WriteLine("Day of year = {0}", mydate.DayOfYear); } catch (Exception exc) { Console.WriteLine(exc); } } } class Date { // Поля public int year; public int month; public int day; static int[] МonthDays = new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; // Свойства public int Year { set { if (value < 1600) throw new ArgumentOfRangeException("Year"); else year = value; } get { return year; } } public int Month { set { if (value < 1 || value > 12) throw new ArgumentOfRangeException("Month"); else month = value; } get { return month; } } public int Day { set { if (value < 1 || value > 31) throw new ArgumentOfRangeException("Day"); else day = value; } get { return day; } } public int DayOfYear { get { return MonthDays[month - 1] + day + (month > 2 && IsLeapYear(year) ? 1 : 0); } } // Метод public static bool IsLeapYear(int year) { return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); } };
Я оставил код в блоках try и catch, так что вы можете поэкспериментировать с некорректными датами. Кстати, для свойства Year я установил минимальное значение 1600, так как для более ранних дат метод IsLeapYear не имеет особого смысла. Осталась нерешенной одна проблема: метод не проверяет согласованность полей между собой. Например, можно задать дату 31 февраля. Такая проверка согласованности наложила бы ограничения на порядок присвоения свойств, так что я обойдусь без нее.
Кроме того, я преобразовал DayOfYear из метода в неизменяемое свойство, потому что значение дня года больше похоже на свойство даты, чем на метод. Иногда бывает сложно определить, что использовать — метод или свойство? Единственное очевидное правило: есть параметр — используй метод.
netlib.narod.ru | < Назад | Оглавление | Далее > |