| 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 | < Назад | Оглавление | Далее > |