Все перечисления в С# происходят от единого базового класса System.Enum. Конечно же, в этом базовом классе предусмотрены методы, которые могут существенно облегчить вашу работу с перечислениями. Первый метод, о котором необходимо упомянуть, — это статический метод GetUnderlyingType(), который позволяет получить информацию о том, какой тип данных используется для представления числовых значений элементов перечисления:
// Получаем тип числовых данных перечисления (в нашем примере это будет System.Byte)
Кроме того, вы можете получать значимые имена элементов перечисления по их числовым значениям. Эту работу за вас выполняет статический метод Enum.Format().В нашем примере переменной типа EmpType соответствовало имя элемента перечисления Contractor (то есть эта переменная разрешалась в числовое значение 100). Для того чтобы узнать, какому элементу переменной соответствует это числовое значение, необходимо вызвать метод Enum.Format, указать тип перечисления, числовое значение (в нашем случае через переменную) и флаг форматирования (в нашем случае - G, что означает вывести как тип string, можно использовать также флаги х — шестнадцатеричное значение и d — десятичное значение):
// Этот код должен вывести на системную консоль строку //"You are a Contractor
EmpType fred;
fred = EmpType.Contractor;
Console.WriteLine("You area {0}”, Enum.Format(typeof(EmpType), fred, "G"));
В System.Enum предусмотрен еще один полезный статический метод — GetValues(). Этот метод возвращает экземпляр System.Array, при этом каждому элементу массива будет соответствовать член указанного перечисления:
// Получаем информацию о количестве элементов в перечислении
Array obj = Enum.GetValues(typeof(EmpType));
Console.WriteLine('This enum has {0} members.", obj.Length);
// А теперь выводим имена элементов перечисления в формате string и соответствующие им числовые значения:
foreach(EmpType e in obj) {
Console.Write("String name: {0}", Enum.Format(typeof(EmpType), e, "G"));
Console.Write( “({0})", Enum.Format(typeof(EmpType), e, "D"));
Console.Write(“ hex: {0}\n", Enum.Format(typeof(EmpType), e, "X"));
}
Кроме того, в классе System.Enum предусмотрено очень полезное свойство IsDefined. Оно позволяет определить, является ли выбранная вами символьная строка элементом указанного перечисления. Например, предположим, что вам потребовалось узнать, является ли значение Salesperson элементом перечисления EmpType:
Последнее, о чем необходимо упомянуть в этом разделе: перечисления С# поддерживают работу с большим количеством перегруженных операторов, которые могут выполнять различные операции с числовыми значениями переменных. Например:
// Какому из этих двух переменных-членов перечисления //соответствует большее числовое значение?
EmpType Joe = EmpType.VP;
EmpType Fran = EmpType.Grunt;
if(Joe < Fran)
Console.WriteLine(“Joe's value is less than Fran's");
else
Console.WriteLine(“Fran's value is less than Joe's");
Определение структур в С#
Структуры С# можно рассматривать как некую особую разновидность классов. С классами структуры роднит многое: для структур можно определять конструкторы (только принимающие параметры), структуры могут реализовывать интерфейсы, структуры могут содержать любое количество внутренних членов. Для структур С# не существует единого базового класса (тип System.Structure в С# не предусмотрен), однако косвенно все структуры являются производными от типа ValueType. Основное назначение ValueType заключается в том, чтобы обеспечить типы данных, производные от System.Object, членами для работы с этими типами данных как со структурными (value-based), когда значения передаются как локальные копии, а не как ссылки на области в памяти.
Синтаксис объявления структуры аналогичен синтаксису объявления класса:
[:список_интерфейсов]
{тело_структуры}
Вот простой пример структуры С#:
// Вначале нам потребуется перечисление
enum EmpType : byte {
Manager = 10,
Grunt = 1,
Contractor = 100,
VP = 9
}
struct Employee {
public EmpType title; // Одно из полей структуры –
// перечисление, определенное выше
public string name;
public short deptID:
}
class StructTester {
public static int Main(string[] args) {
// Создаем и присваиваем значения Фреду
Employee fred;
fred.deptID = 40;
fred.name = "Fred";
fred.title = EmpType.Grunt;
return 0;
}}
Мы создали структуру Employee (для нее была выделена память в области стека) и теперь можем обращаться к каждому члену структуры, используя формат имя_структуры.имя_члена. Вполне возможно, что в реальном приложении для более удобного присвоения значений членам структуры нам придется определить свой собственный конструктор или несколько конструкторов. В связи с этим обходимо помнить, что вы не можете переопределить конструктор для структуры по умолчанию — тот конструктор, который не принимает параметров, ваши конструкторы обязательно должны принимать один или несколько параметров:
// Для структур можно определить конструкторы, но все созданные вами конструкторы должны принимать параметры
struct Employee {
// Поля
public EmpType title;
public string name;
public short deptID;
// Конструктор
public Employee (EmpType et, string n, short d) {
title = et;
name = n;
deptID = d;
}}
При помощи такого определения структуры, в котором предусмотрен конструктор, вы можете создавать новых сотрудников следующим образом:
class StructTester {
// Создаем Мэри и присваиваем ей значения при помощи конструктора
public static int Main(string[] args) {
// Длявызова нашего конструктора мы обязаны использовать
Конечно же, структуры могут быть использованы в качестве принимаемых и возвращаемых методами параметров. Например, пусть в нашем классе StructTester будет предусмотрен метод DisplayEmpStats ():
// Извлекаем интересующую нас информацию из структуры Employee
public void Displ ayEmpStats (Employee e) {
Console.WriteLine(“Here is {0}\'s info:", e.name);