Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsii_po_programmirovaniyu_3_semestr.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
2.11 Mб
Скачать

Свойства

Свойства расширяют возможности полей данных. Они представляют собой типизированные объекты, у которых можно получить значение и записать в них новое значение. При выполнении этих действий выполняется определяемый программистом код. Синтаксис определения полей следующий:

<модификаторы> <тип> <имя>

{

get { /* Тело get */ }

set { /* Тело set */ }

}

В теле get пишется код, который выполняется при получении значения свойства. В теле set пишется код, который выполняется при установке нового значения. При этом в set доступно присваеваемое значение через ключевое слово value:

public class SampleClass

{

private static int a;

public static int A

{

get { return a; }

set { a = value; }

}

public static void Main() { A = 2; Console.WriteLine("A = {0}", A); }

}

Этот пример демонстрирует распространенный прием инкапсуляции полей.

Свойство – это пара методов со специальными именами. Метод set() вызывается при изменении значения свойства, метод get() – при получении значения свойства. Обращение к свойству выглядит как обращение к полю данных, но транслируется в вызов одного из двух методов. Имя метода обычно близко к имени поля (например, если имя переменной - name, то свойству дают имя - Name).

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

* чтение и запись (Read, Write); * чтение и запись только при первом обращении (Read, Write-once); * только чтение (Read-only); * только запись (Write-only); * ни чтения, ни записи (Not Read, Not Write).

Открытость свойств (атрибут public) позволяет реализовать только первую стратегию.

class PropertyClass1

{

private int x;

public int X

{

set { x=value; }

get { return x; }

}

}

Определяя в свойстве только один из двух методов, получаем свойства только для чтения или только для записи.

// Стратегия только чтения или только записи

class PropertyClass1

{

private int x, y;

public int X { get { return x; } }

public int Y { set { y=value; } }

}

Однако, возможен и другой вариант реализации той же стратегии, использующий манипуляцию уровнями доступа к методам, реализующим свойство:

// Та же стратегия - только чтения или только записи

class PropertyClass1

{

private int x, y;

public int X

{

private set { x=value; }

get { return x; }

}

public int Y

{

set { y=value; }

private get { return x; }

}

}

Индексаторы

Одним из важных направлений развития языков программирования является удобство и наглядность кода. Именно стремление упростить структуру кода привело в свое время к перегрузке операторов в С++ и свойств в Object Pascal. Предлагая новый язык специально для своей новой платформы, Microsoft, разумеется, не могла не учесть это сторону вопроса. Поэтому язык включает в себя свойства (properties) и индексаторы (indexers).

При написании приложений часто возникает необходимость создавать объекты, представляющие собой коллекцию других объектов (они не обязательно могут явно хранить в себе все эти объекты, а только предоставлять доступ к ним). В языках вроде Cи или Java для этого использовались специальные функции (методы) вроде GetItem( int index ). Конечно, это возможный подход, но часто, когда нужно часто обращаться к элементам коллекции, неудобно каждый раз писать такие громоздкие конструкции.

Свойство, обеспечивающее доступ к массиву, называется индексатор. Синтаксически объявление индексатора - такое же, как и в случае свойств, но методы get и set приобретают аргументы по числу размерности массива, задающего индексы элемента, значение которого читается или обновляется. Важным ограничением является то, что у класса может быть только индексатор со стандартным именем this.

Индексаторы предоставляют синтаксис сходный с тем, который используется при адресации массива, за исключением того, что в качестве типа данных индекса, можно использовать любой тип. Для того, чтобы объявить в классе индексатор, нужно использовать следующий синтаксис:

<тип> this [список_параметров]

где тип – это тип возвращаемого значения (тип элемента коллекции), а список параметров – это типы и имена параметров, используемых для идентификации элемента коллекции. Индексатор может иметь любые модификаторы, кроме static, а к его параметрам нельзя применять модификаторы out и ref.

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

public object this [int index]

{

get { return GetItem(index); }

set { SetItem(index, value); }

}

Для полной ясности картины, приведем небольшой пример:

using System;

public CustomIndexerClass

{

// Объявляем внутренний массив, где будут храниться действительные значения

private int internalArray = new int[10];

// Объявляем индексатор

public int this [int index]

{

get // Доступ на чтение

{

// Проверка границ

if (index < internalArray.GetLowerBound(0) ||

index > internalArray.GetUpperBound(0))

return 0;

// Вoзвращаем значение соответствующего элемента массива

return internalArray[index];

}

set

{

// Проверка границ и запись нового значения

if (index >= internalArray.GetLowerBound(0) &&

index <= internalArray.GetUpperBound(0))

internalArray[index] = value;

}

}

public class ApplicationClass

{

public static void Main()

{

CustomIndexerClass myIndexer = new CustomIndexerClass();

myIndexer[1] = 10;

myIndexer[5] = 7;

for (int i = 0; i < 10; i++)

Console.WriteLine("myIndexer[{0}] = {1}\n", i, myIndexer[i]);

}

}

}

Эта программа создает класс, имеющий индексатор, который просто читает или записывает значения во внутреннем массиве. Главная программа сначала изменяет несколько ячеек массива, пользуясь индексатором, а затем читает все его ячейки последовательно.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]