Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Yazyk_C_i_osnovy_platformy_NET.docx
Скачиваний:
16
Добавлен:
11.05.2015
Размер:
198.13 Кб
Скачать

10. Свойства и индексаторы

Свойствакласса призваны предоставить защищённый доступ к полям. Как и в большинстве объектно-ориентированных языков, в C# непосредственная работа с полями не приветствуется. Поля класса обычно объявляются с модификаторомprivate, а для доступа к ним используются свойства.

Рассмотрим базовый синтаксис описания свойства:

модификаторы тип-свойства имя-свойства

{

get { операторы }

set { операторы }

}

Синтаксис описания заголовка свойства напоминает синтаксис описания обычного поля. Тип свойства обычно совпадает с типом того поля, для обслуживания которого свойство создаётся. У свойства присутствует специальный блок, содержащий методы для доступа к свойству. Данный блок состоит из get-части иset-части, далее называемыхаксессоримутаторсоответственно. Одна из частей может отсутствовать, так получаетсясвойство только для чтенияилисвойство только для записи. Аксессор отвечает за возвращаемое свойством значение и работает как функция. Мутатор работает как процедура, устанавливающая значение свойства. Считается, что параметр, передаваемый в мутатор, имеет специальное имяvalue.

Рассмотрим пример класса, имеющего свойства:

publicclassStudent

{

privateint_age;

privatestring_name;

publicintAge

{

get

{

return_age;

}

set

{

_age = value > 0 ? value : 0; // проверка корректности

}

}

publicstringName

{

get{return"My name is "+ _name; }

set { _name = value; }

}

}

Свойства транслируются при компиляции в вызовы методов. В скомпилированный код класса добавляются методы со специальными именами get_Name()иset_Name(), гдеName– это имя свойства. Побочным эффектом трансляции является то, что пользовательские методы с данными именами допустимы в классе, только если они имеют сигнатуру, отличающуюся от методов, соответствующих свойству.

Как правило, свойства открыты, то есть снабжаются модификатором доступа public. Однако иногда логика класса требует разделения права доступа чтения и записи свойства. Например, чтение позволено всем, а запись – только из методов того класса, где свойство объявлено. В C# разрешено при описании свойства указывать модификаторы доступа для аксессоров и мутаторов. При этом действуют два правила. Во-первых, модификатор может быть только у одной из частей. Во-вторых, он должен понижать видимость части по сравнению с видимостью всего свойства:

publicclassSomeClass

{

publicintProp

{

get { return 0; }

private set { }

}

}

Достаточно часто свойство содержит только простейший код доступа к полю. Вот фрагмент класса с таким свойством:

publicclassPerson

{

privatestring_name;

publicstringName

{

get{return_name; }

set{ _name =value; }

}

}

Чтобы облегчить описание таких свойств-«обёрток», в C# имеются автосвойства(auto properties). Используя автосвойства, приведённый фрагмент кода можно переписать следующим образом:

public class Person

{

publicstringName {get;set; }

}

В этом случае компилятор сам сгенерирует необходимое поле класса, связанное со свойством. Обратите внимание: в автосвойстве должны присутствовать и часть get, и частьset. При необходимости получить аналог классических свойств только для чтения необходимо использовать модификаторы доступа для частей:

publicclassPerson

{

publicstringName {get;privateset; }

}

Кроме скалярных свойств язык C# поддерживает индексаторы. При помощи индексаторов осуществляется доступ к коллекции данных, содержащихся в объекте, с использованием привычного синтаксиса для доступа к элементам массива – пары квадратных скобок и индекса.

Объявление индексатора напоминает объявление обычного свойства:

модификаторы тип this[параметры] { get-и-set-блоки }

Параметры индексатора служат для описания типа и имён индексов, применяемых для доступа к данным. Параметры индексатора могут быть описаны как параметры-значения или как параметр-список (с использованием params). Также допустимо использование опциональных параметров.

Рассмотрим пример класса, содержащего индексатор. Пусть данный класс описывает студента с набором оценок:

publicclassStudent

{

privatereadonlyint[] _marks =newint[5];

publicintthis[inti]

{

get

{

returnBelongs(i, 0, 4) ? _marks[i] : 0;

}

set

{

if(Belongs(i, 0, 4) && Belongs(value, 1, 10))

_marks[i] = value;

}

}

privateboolBelongs(intx,intmin,intmax)

{

return(x >= min) && (x <= max);

}

}

При использовании индексатора указывается имя объекта и значение индекса (или индексов) в квадратных скобках. Допустимы именованные индексы (по аналогии с именованными аргументами метода). Если необходимо использовать индексатор в пределах класса, применяют синтаксис this[значение].

varstudent =newStudent();

student[1] = 8;

student[3] = 4;

for(inti = 0; i < 5; i++)

{

Console.WriteLine(student[i]);

}

В одном классе нельзя объявить два индексатора, у которых совпадают типы параметров. Можно объявить индексаторы, у которых параметры имеют разный тип или количество параметров различается1.