Помощь в написании студенческих работ
Антистрессовый сервис

Расширяющие методы и деконструкторы

РефератПомощь в написанииУзнать стоимостьмоей работы

В списке аргументов перечисляются имена переменных, типы и последовательность которых должны полностью соответствовать спецификации выходных (с модификаторами out) параметров деконструктора. Как и при непосредственном обращении к деконструктору, переменные, играющие роль аргументов, могут быть объявлены «на лету», т. е. в списке аргументов. Однако (в отличие от списка аргументов прямого вызова… Читать ещё >

Расширяющие методы и деконструкторы (реферат, курсовая, диплом, контрольная)

Расширяющий метод позволяет дополнять существующий класс (или другой тип: структуру, интерфейс) методами объектов, не изменяя декларации класса. Это особенно удобно в тех случаях, когда у программиста нет доступа к коду декларации класса. Несмотря на то, что мы еще не рассмотрели полностью синтаксис объявления классов, расширяющие методы мы уже можем определять, так как каждый из них является просто по-особому декларированный статический метод статического класса. Особенностей декларации две. Первая состоит в том, что первый параметр расширяющего метода должен иметь тип того класса, для которого выполняется расширение. Вторая особенность — первый параметр должен быть снабжен модификатором this.

Для иллюстрации возможностей расширяющих методов предположим, что нужен метод, формирующий случайные целые числа с четными значениями, не превышающие заданной величины. Средства для программной генерации случайных чисел определены в библиотечном классе System.Random. Для получения целых чисел из диапазона [0; Мах) используется нестатический метод с заголовком:

int Next (int Max).

Метода для получения только четных случайных чисел в классе Random нет. Для дополнения объектов класса Random соответствующим методом определим такой класс: public static class RandomExpansion.

{

public static int EvenNumber (this Random rd, int max).

{

if (max < 2) return 0;

while (true).

{

int res = rd. Next (max); if (res % 2 == 0) return res;

} }

} // cLass RandomExpansion

Первый параметр метода передает в его тело ссылку rd на объект класса Random. С помощью этой ссылки выполняется обращение к методу Next объекта класса Random и формируется случайное целое число. Если оно четное, то его значение — результат метода EvenNumber ().

К расширяющему методу EvenNumberO можно обращаться так, как будто это метод объектов класса Random:

class Program.

{

static void Main ().

{

Random rnd = new Random ();

for (int k = 0; k < 10; k++).

Console.Write (rnd.EvenNumber (12) + ««);

} }

Результат выполнения кода:

2 10 8 10 464 628.

В методе Main () создан объект класса Random, ссылка на который позволяет вызвать метод EvenNumberO с единственным аргументом.

Так как метод EvenNumberO декларируется как статический метод класса RandomExpansion, то его можно вызывать и как обычный статический метод. Например, так:

int stat = RandomExpansion. EvenNumber (new Random (), 20);

В таком обращении к расширяющему методу требуется явно указать первый аргумент.

Еще одна возможность получить доступ к членам данных (к полям и свойствам) экземпляра класса — применение деконструктора.

Деконструктор — это метод класса со специальным названием Deconstructor (), имеющий не менее двух параметров с модификатором out. Назначение деконструктора — «извлечение» данных из объектов. Таким образом, деконструктор выполняет работу, в некотором смысле противоположную той, которую обычно выполняет конструктор экземпляров класса.

С помощью параметра деконструктора можно вернуть не только значение поля или свойства, но и достаточно произвольное значение, вычисляемое на основе данных объекта. По существу, деконструктор — это обычный нестатический метод экземпляров типа, но для его вызова введен специальный удобный синтаксис. Именно этот синтаксис требует, чтобы у деконструктора было не менее двух параметров с модификаторами out. Если обращаться к деконструктору с помощью уточненного имени, квалифицированного ссылкой на объект, то можно определить в классе и применять деконструктор с одним выходным параметром.

Для иллюстрации особенностей декларации деконструкторов приведем объявление класса правильных многоугольников. Известно, что периметр Р правильного n-угольника, описанного около окружности радиуса г, равен 2*n*r*tg (PI/n), площадь этого многоугольника S равна n*r*r*tg (PI/n). Используя эти сведения, так определим класс правильных многоугольников:

public class Polygon.

{ // Класс многоугольников

int Numb { get; set; } // Число сторон

double Radius { get; set; } // Радиус вписанной окружности

public Polygon (int n = 3, double r = 1).

{ // конструктор Numb = n;

Radius = r;

}

public double Perimeter { // Периметр многоугольника get.

{ // аксессор свойства

double term = Math. Tan (Math.PI / Numb); return 2 * Numb * Radius * term;

} }

// Площадь многоугольника:

public double Area => Perimeter * Radius / 2;

// Деконструктор с двумя параметрами:

public void Deconstruct (out int n, out double r).

{ r = Radius; n = Numb; }.

// Деконструктор с тремя параметрами:

public void Deconstruct (out int n, out double r,.

out double ambit).

{ r = Radius; n = Numb; ambit = Perimeter; }.

}

В классе Polygon два автореализуемых свойства (Numb и Radius) задают, соответственно, число сторон и радиус вписанной в многоугольник окружности. Свойства, определяющие периметр и площадь конкретного многоугольника (Perimeter и Area), доступны только для чтения, причем в декларации свойства Area используется синтаксис сжатия до выражения.

В классе Polygon конструктор общего вида с умалчиваемыми значениями параметров и два деконструктора. Первый из них — с двумя параметрами:

public void Deconstruct (out int n, out double r).

{r = Radius; n = Numb;}.

Параметры этого деконструктора возвращают значения автореализуемых свойств объекта класса.

Список параметров второго деконструктора дополнен третьим параметром (out double ambit), позволяющим получить значение свойства, вычисляющего периметр многоугольника, представленного объектом класса.

Синтаксис языка C# допускает несколько вариантов организации вызова деконструктора. Так как деконструктор определяется как открытый нестатический метод класса, то и обращаться к нему можно непосредственно, используя ссылку на объект класса:

Polygon poly = new PolygonQ;

poly.Deconstruct (out int n, out double r);

Console.WriteLine («Numb = «+ n + «; Radius = «+ r);

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

Numb = 3; Radius = 1.

Для упрощения вызова деконструктора в C# 7.0 введен специальный синтаксис:

(список_аргументов) = ссылка_на_объект;

В списке аргументов перечисляются имена переменных, типы и последовательность которых должны полностью соответствовать спецификации выходных (с модификаторами out) параметров деконструктора. Как и при непосредственном обращении к деконструктору, переменные, играющие роль аргументов, могут быть объявлены «на лету», т. е. в списке аргументов. Однако (в отличие от списка аргументов прямого вызова деконструктора) аргументы (даже при их объявлении «на лету») не снабжаются модификаторами out.

Пример обращения к деконструктору с тремя параметрами, когда типы аргументов объявлены «на лету»:

(int nv, double rv, double pv) = poly;

Console.WriteLine («Numb = «+ nv +.

"; Radius = «+ rv + «; Perimeter = «+ pv);

Результат выполнения такого фрагмента программы:

Numb = 3; Radius = 1; Perimeter = 10,39 230 484Б4133.

Тот же результат будет получен, если заменить один оператор обращения к деконструктору таким кодом:

int nv;

double rv, pv;

(nv, rv, pv) = poly;

Так как спецификация параметров деконструктора однозначно определяет требования к аргументам, то возможно применение неявной типизации. Пример обращения к деконструктору с двумя параметрами, когда типы аргументов выводит компилятор:

(var num, var rad) = poly;

Console.WriteLine («Numb = «+ num + Radius = «+ rad);

Результат выполнения приведенного фрагмента программы:

Numb = 3; Radius = 1.

Допустимо и такое сокращение записи вызова деконструктора:

var (num, rad) = poly;

Если при обращении к деконструктору не нужны некоторые из значений, то вместо соответствующих им аргументов используют подстановку: «_». Например, чтобы получить только значение периметра, используют такой код:

var (_, perimeter) = poly;

Console.WriteLine («Perimeter = «+ perimeter);

Результат выполнения приведенного фрагмента программы:

Perimeter = 10,3 923 048 454 133.

До сих пор мы рассматривали возможности деконструкторов на примере класса, определенного программистом, когда деконструктор можно декларировать непосредственно в объявлении класса.

Расширяющие методы позволяют создавать деконструкторы и для структур и тех классов, код которых программисту недоступен. В качестве примера определим в виде расширяющих методов деконструкторы для библиотечной структуры Complex, предназначенной для работы с комплексными числами. Особенности структур будут рассмотрены в следующих главах, но расширяющие методы для структур и обращения к свойствам структур внешне не отличаются от расширяющих методов для классов, поэтому пример будет понятен.

Примечание. Библиотечная структура Complex принадлежит пространству имен System. Numerics и находится в сборке System.Numerics.dll.

Для подключения сборки к проекту необходимо в обозревателе решений «развернуть» список проекта, правой кнопкой мыши активировать пункт «ссылки». Из развернувшегося меню выбрать пункт «Добавить ссылку…», на панели «Менеджер ссылок» активировать пункт «System.Numerics» и нажать клавишу «ОК».

Чтобы сборка стала доступна в коде, потребуется директива:

using System. Numerics; // Пространство имен для Complex

В структуре Complex четыре свойства:

Imaginary — мнимая часть комплексного числа;

Magnitude — модуль (абсолютное значение) комплексного числа; Phase — аргумент (фаза) комплексного числа;

Real — вещественная часть комплексного числа Чтобы получать из экземпляра структуры типа Complex значения перечисленных свойств, определим статический класс ComplexHelper с методом-деконструктором, расширяющим возможности типа Complex. Текст программы с этим классом:

using System;

using System. Numerics; // Для типа «Complex» … public static class ComplexHelper {.

// Деконструктор (вернет все свойства экземпляра): public static void Deconstruct (this Complex cm, out double magnitude, out double phase, out double real, out double image).

{

magnitude = cm. Magnitude; phase = cm. Phase; real = cm. Real; image = cm. Imaginary;

>

} // class ComplexHelper class Program {.

static void Main ().

{

Complex cmp = new Complex (4, 6);

(double module, double argument, _, _) = cmp;

Console.WriteLine («module = «+ module);

Console.WriteLine («argument = «+ argument);

} }

Результаты выполнения программы:

module = 7,21 110 255 092 798 argument = 0,982 793 723 247 329.

У деконструктора пять параметров. Первый с модификатором this соотносит метод с экземпляром структуры Complex. Остальные четыре параметра возвращают соответствующие названиям значения свойств комплексного числа. В методе Main () создан экземпляр структуры Complex и представляющая этот экземпляр ссылка (Complex cmp). При обращении к конструктору в качестве аргументов указаны два аргумента — значения вещественной и мнимой частей комплексного числа. Они известны из кода вызова конструктора, поэтому при обращении к деконструктору явно декларированы на лету только переменные для аргументов, получающих значения модуля и аргумента комплексного числа. Результаты выполнения программы иллюстрируют получаемые значения.

Контрольные вопросы и задания

  • 1. Объясните принципы инкапсуляции и ее применения к классам.
  • 2. В чем отличия свойств от полей?
  • 3. Приведите формат объявления свойства.
  • 4. Какие модификаторы используются в объявлении свойства?
  • 5. Что такое тип свойства?
  • 6. Что такое тело аксессора в объявлении свойства?
  • 7. Какие модификаторы допустимы в объявлении аксессора?
  • 8. Каким идентификатором представлено в set-аксессоре новое значение свойства?
  • 9. Как можно задать значение свойства, пригодного только для чтения?
  • 10. Объясните назначение механизма автореализуемых свойств.
  • 11. В каком случае для декларации свойства можно применять синтаксис сжатия до выражения?
  • 12. Что такое скрытые поля?
  • 13. Объясните роль служебного слова this в индексаторе.
  • 14. Может ли в одном классе быть несколько индексаторов?
  • 15. Какой тип допустим для параметра индексатора?
  • 16. В каком случае для индексатора разрешен синтаксис сжатия до выражения?
  • 17. Назовите особенности декларации расширяющего метода.
  • 18. Какими способами можно обращаться к расширяющим методам?
  • 19. Что такое деконструктор?
  • 20. Какие ограничения наложены на параметры деконструктора?
  • 21. В чем особенность вызова деконструктора?
  • 22. Как при обращении к деконструктору игнорировать получение значения аргумента?
Показать весь текст
Заполнить форму текущей работой