Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky.rtf
Скачиваний:
27
Добавлен:
22.03.2016
Размер:
11.9 Mб
Скачать

15.3. Структуры

Структуры

"структура"

во многом похожи на классы, но имеют и

существенные отличия. Как и класс, структура вводит тип. Однако, в отличие от

классов структуры не могут участвовать в наследовании и поэтому в декларации

структуры отсутствует спецификация базы.

Определение (иначе декларация или объявление

"структура:объявление

структуры" ) структуры (структурного типа) имеет следующий формат (указаны не

все части полного формата):

модификаторы_структурыopt

struct имя_структуры интерфейсы_структурыopt

тело_структуры

В декларации структуры struct – служебное слово "служебное слово: struct"

,

имя_структуры – выбранный программистом идентификатор, определяющий имя

структурного типа. Тело_структуры – заключенная в фигурные скобки

последовательность объявлений (деклараций) членов структуры. Модификаторов

структуры

"структура:модификатор структуры"

меньше чем модификаторов

класса. Могут использоваться: new, public, protected, internal, private.

Модификаторы определяют статус доступа структурного типа и они

практически все уже рассмотрены в связи с классами.

Структуры не участвуют в наследовании, однако, структуры могут служить

реализацией интерфейсов, перечисленных в декларации после имени структуры.

Элемент декларации интерфейсы_структурыopt – это список интерфейсов, перед

которым помещено двоеточие.

Членами структуры "структура:члены структуры" могут быть: константы,

поля,

методы,

свойства,

индексаторы,

события,

операции,

конструкторы

экземпляров, статические конструкторы и вложенные типы. В отличие от классов

членом структуры не может быть финализатор деструктор).

Структуры всегда наследуются от System.ValueType, которой в свою очередь

является производным классом от System.Object "класс: System.Object" \y "класс" .

Поэтому в структурах присутствуют уже рассмотренные ранее открытые и

защищённые методы класса Object. Напомним основные из них: ToString(),

GetHashCode(), Equals(), GetType().

Существенным отличием структур от классов является то, что класс вводит

тип ссылок, а структура – тип значений

"тип:тип значений" . Таким образом,

каждой переменной структурного типа соответствует конкретный экземпляр

структуры. И, присвоив новой переменной значение другой переменной, уже

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

Прежде чем привести пример, отметим ещё некоторые отличия структур от

классов.

Во-первых,

в

объявлении

поля

структуры

нельзя

использовать

инициализатор. Во-вторых, в каждое объявление структуры автоматическ

и

встраивается

конструктор

умолчания

без

параметров.

Назначение

этого

конструктора – инициализировать все члены структуры значениями, которые

соответствуют их типам по умолчанию. В-третьих, в структуре нельзя явно

объявить конструктор умолчания

"конструктор умолчания"

без параметров. В

качестве иллюстрации возьмем класс "точка на плоскости" и эквивалентную ему

структуру:

// 15_07.cs - структуры и классы "точка на плоскости"

using System;

class PointC // класс

{

double x = 10, y = 20;

public PointC() { y -= 5; }

public double X { get { return x; } set { x = value; } }

public double Y { get { return y; } set { y = value; } }

}

class Program

{

static void Main()

{

PointC pc = new PointC();

PointC pc1 = pc;

pc1.X = 10.2;

Console.WriteLine("X={0}; Y={1}", pc.X, pc.Y);

PointS ps = new PointS();

PointS ps1 = ps;

ps1.X = 10.2;

Console.WriteLine("X={0}; Y={1}", ps.X, ps.Y);

}

}

struct PointS // структура

{

//double x = 10, y = 20; // Error!

//public PointS() { y -= 5; } // Error!

double x, y;

public double X { get { return x; } set { x = value; } }

public double Y { get { return y; } set { y = value; } }

}

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

X=10,2; Y=15

X=0; Y=

0

В классе PointC выполняется явная инициализация полей x, y. Конструктор

умолчания PointC() изменяет значение поля y.

В структурах инициализация полей невозможна и недопустимо присутствие

явного определения конструктора умолчания. Попытки нарушить эти правила в

структуре PointS отмечены в тексте программы комментариями // Error!

В программе pc – имя ссылки, ассоциированной с объектом класса PointC. В

противоположность этому ps – имя переменной, значением которой является объект

типа PointS. Объявив ещё одну ссылку pc1 типа PointC и присвоив ей значение pc,

мы связываем две ссылки с одним объектом класса PointC. Квалифицированные

имена pc.X и pc1.X обеспечивают доступ к одному и тому же свойству одного и того

же объекта класса PointC.

Выполнение присваивания PointS ps1 = ps; приводит к созданию копии

структуры, представляемой переменной ps. Таким образом, после выполнения

присваивания квалифицированные имена ps.X и ps1.X именуют свойства

независимых друг от друга объектов одного структурного типа PointS.

Поясним отсутствие в структурах финализатора. Финализатор "финализатор"

– это метод, который автоматически вызывается всякий раз, когда сборщик мусора

убирает более неиспользуемый в программе объект из той части памяти, которую

называют кучей. Так как для объектов с типами значений память выделяется не в

куче а в стеке, а сборка мусора на стек не распространяется, то финализатор для

структур не нужен.

Копирование структуры "структура:копирование структуры" выполняется не

только при выполнении присваивания переменных структурного типа, но и при их

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

Следующая программа иллюстрирует особенности применения структур в методах.

// 15_08.cs - структуры и методы

using System;

struct PointS // структура

{

double x, y;

public double X { get { return x; } set { x = value; } }

public double Y { get { return y; } set { y = value; } }

public PointS(double xi, double yi) { x = xi; y = yi; }

}

class Program

{

static PointS reverse(PointS dot)

{

dot.X = -dot.X;

dot.Y = -dot.Y;

return dot;

}

static void Main()

{

PointS one = new PointS(12, 8);

PointS two = reverse(one);

Console.WriteLine("one.X={0}; one.Y={1}", one.X, one.Y);

Console.WriteLine("two.X={0}; two.Y={1}", two.X, two.Y);

}

}

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

one.X=12; one.Y=8

two.X=-12; two.Y=-8

В программе объявлен структурный тип PointS. В нём два закрытых поля (x,y),

два ассоциированных с этими полями открытых свойства (X,Y) и открытый

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

reverse() получает в качестве передаваемого по значению параметра структуру,

изменяет с помощью свойств значения её полей x и y, и возвращает структуру как

результат в точку вызова метода.

В методе Main() объявлены две переменные PointS one и PointS two. Первая из

них связана со структурой, инициализированной обращением к конструктору

PointS(12,8). Вторая получает в качестве значения результат, возвращаемый

методом reverse(one).

Очень важен тот факт, что после выполнения метода reverse(), аргументом

которого служит объект one, значение этого объекта не изменилось. Это

подтверждает тот факт, что при присваивании структур, при использовании

структуры в качестве передаваемого по значению параметра или возвращаемого

методом

значения

создаётся

копия

структуры,

в

дальнейшем

полностью

независимая от оригинала.

Если в рассмотренной программе заменить структуру на класс (т.е. заменить

struct PointS на class PointC), то результат выполнения программы будет таким:

one.X=-12; one.Y=-8

two.X=-12; two.Y=-8

Тот же самый результат будет получен, если параметр структурного типа

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

образом изменить заголовок метода:

static PointS reverse(ref PointS dot).

Соответствующим образом изменится вызов метода:

two = reverse(ref one);

Как уже сказано, в объявлениях структур нельзя инициализировать поля.

Кроме того, нельзя явным образом определить конструктор без параметров. Все

поля объектов структурного типа без вмешательства извне инициализируются

умалчиваемыми значениями, соответствующими типам полей. Например, для

арифметических типов это нули, для ссылок null. Например, объявим ссылку на

массив структур и определим массив:

PointS[ ] ar = new PointS[50];

Элементами массива в этом примере станут структуры, для которых поля x и y

будут иметь нулевые значения.

Переменную с типом структуры можно создать без явного обращения к

конструктору и без применения операции new. Однако такая переменная в этом

случае создаётся как неинициализированная и ей нужно присвоить подобающее ей

значение. После этого всем членам структуры, присваиваются значения полей

инициализирующей структуры

.

Следующая программа иллюстрирует приведённые сведения о структурах.

// 15_09.cs - структуры, конструктор умолчания

using System;

struct PointS // структура

{

double x, y;

public double X { get { return x; } set { x = value; } }

public double Y { get { return y; } set { y = value; } }

}

class Program

{

static void Main()

{

PointS[] ar = new PointS[50];

Console.WriteLine("ar[0].X={0}; ar[0].Y={1}", ar[0].X, ar[0].Y);

PointS three = new PointS();

three.Y = 2.34;

Console.WriteLine("three.X={0}; three.Y={1}", three.X, three.Y);

PointS four; // неинициализированная переменная!

four = three;

Console.WriteLine("four.X={0}; four.Y={1}", four.X, four.Y);

}

}

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

ar[0].X=0; ar[0].Y=0

three.X=0; three.Y=2,34

four.X=0; four.Y=2,34

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

классов в ряде случаев повышает быстродействие программ и уменьшается объём

занимаемой памяти. Связано это с тем, что доступ к объекту класса выполняется

косвенно, а обращение к структуре – непосредственно. Имя экземпляра структуры

является именем переменной, значением которой служит объект структурного типа.

В то же время при использовании структуры в качестве параметра,

передаваемого по значению, или возвращаемого методом значения необходимы

временные затраты на копирование всех полей структуры.

Соседние файлы в папке CSBasicCourse2ndedPodbelsky