Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Руководство_по_C#.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
10.01 Mб
Скачать

Назначение структур

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

Более того, работа со структурой не приводит к ухудшению производительности, столь характерному для обращения к объекту класса. Ведь доступ к структуре осуществляется непосредственно, а к объектам — по ссылке, поскольку классы относятся к данным ссылочного типа. Косвенный характер доступа к объектам подразумевает дополнительные издержки вычислительных ресурсов на каждый такой доступ, тогда как обращение к структурам не влечет за собой подобные издержки. И вообще, если нужно просто сохранить группу связанных вместе данных, не требующих наследования и обращения по ссылке, то с точки зрения производительности для них лучше выбрать структуру.

Любопытно, что в С++ также имеются структуры и используется ключевое слово struct. Но эти структуры отличаются от тех, что имеются в C#. Так, в С++ структура относится к типу класса, а значит, структура и класс в этом языке практически равноценны и отличаются друг от друга лишь доступом по умолчанию к их членам, которые оказываются закрытыми для класса и открытыми для структуры. А в C# структура относится к типу значения, тогда как класс — к ссылочному типу.

9.7Перечисления

Перечисление (enumeration) — это определяемый пользователем целочисленный тип. Когда вы объявляете перечисление, то специфицируете набор допустимых значений, которые могут принимать экземпляры перечислений. Но мало того — этим значениям еще должны быть присвоены имена, понятные для пользователей. Если где-то в коде попытаться присвоить экземпляру перечисления значение, не входящее в список допустимых, компилятор выдаст ошибку.

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

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

  • Перечисления делают код яснее, позволяя обращаться к целым значениям, называя их осмысленными именами вместо малопонятных "магических" чисел.

  • Перечисления облегчают ввод исходного кода. Когда вы собираетесь присвоить значение экземпляру перечислимого типа, то интегрированная среда Visual Studio с помощью средства IntelliSense отображает всплывающий список с допустимыми значениями, что позволяет сэкономить несколько нажатий клавиш и напомнить о возможном выборе значений.

Перечислимый тип данных объявляется с помощью ключевого слова enum. Ниже приведена общая форма объявления перечисления:

enum имя {список_перечисления};

где имя — это имя типа перечисления, а список_перечисления — список идентификаторов, разделяемый запятыми.

Следует особо подчеркнуть, что каждая символически обозначаемая константа в перечислении имеет целое значение. Тем не менее, неявные преобразования перечислимого типа во встроенные целочисленные типы и обратно в C# не определены, а значит, в подобных случаях требуется явное приведение типов. Кроме того, приведение типов требуется при преобразовании двух перечислимых типов. Но поскольку перечисления обозначают целые значения, то их можно, например, использовать для управления оператором выбора switch или же оператором цикла for.

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

Давайте рассмотрим пример использования перечислений:

using System;

namespace ConsoleApplication1

{

// Создать перечисление

enum UI : byte { Name, Family, ShortName = 5, Age, Sex }

class Program

{

static void Main()

{

UI user1;

for (user1 = UI.Name; user1 <= UI.Sex; user1++)

Console.WriteLine("Элемент: \"{0}\", значение {1}", user1,

(int)user1);

user1 = (UI)12;

Console.WriteLine("user1 = (UI)12; user1=={0}",user1);

Console.ReadLine();

}

}

}

Вывод программы:

Элемент: "Name", значение 0

Элемент: "Family", значение 1

Элемент: "2", значение 2

Элемент: "3", значение 3

Элемент: "4", значение 4

Элемент: "ShortName", значение 5

Элемент: "Age", значение 6

Элемент: "Sex", значение 7

user1 = (UI)12; user1==12

Значение одной или нескольких символически обозначаемых констант в перечислении можно задать с помощью инициализатора. Для этого достаточно указать после символического обозначения отдельной константы знак равенства и целое значение. Каждой последующей константе присваивается значение, которое на единицу больше значения предыдущей инициализированной константы. В приведенном выше примере инициализируется константа ShortName.

По умолчанию в качестве базового для перечислений выбирается тип int, тем не менее перечисление может быть создано любого целочисленного типа, за исключением char. Для того чтобы указать другой тип, кроме int, достаточно поместить этот тип после имени перечисления, отделив его двоеточием, как в примере:

enum UI : byte { Name, Family, ShortName = 5, Age, Sex }

Изменять базовый тип перечислений удобно в случае создания таких приложений .NET, которые будут развертываться на устройствах с небольшим объемом памяти (таких как поддерживающие .NET сотовые телефоны или устройства PDA), чтобы экономить память везде, где только возможно. Естественно, если для перечисления в качестве базового типа указан byte, каждое значение в этом перечислении ни в коем случае не должно выходить за рамки диапазона его допустимых значений.

Перечисления очень широко применяются во всех библиотеках базовых классов .NET. Например, в ADO.NET множество перечислений используется для обозначения состояния соединения с базой данных (например, открыто оно или закрыто) и состояния строки в DataTable (например, является она измененной, новой или отсоединенной). Поэтому в случае применения любых перечислений следует всегда помнить о наличии возможности взаимодействовать с парами "имя/значение" в них с помощью членов System.Enum.