Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

1.9Интерфейсы

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

Для интерфейсов допускается множественное наследование. В следующем примере интерфейс IComboBox одновременно наследуется от интерфейсов ITextBox и IListBox.

interface IControl { void Paint(); }

interface ITextBox: IControl { void SetText(string text); }

interface IListBox: IControl { void SetItems(string[] items); }

interface IComboBox: ITextBox, IListBox {}

Классы и структуры способны реализовывать несколько интерфейсов. В следующем примере класс EditBox реализует одновременно интерфейсы IControl и IDataBound.

interface IDataBound { void Bind(Binder b); }

public class EditBox: IControl, IDataBound { public void Paint() {...}

public void Bind(Binder b) {...} }

Если класс или структура реализует конкретный интерфейс, экземпляры такого класса или такой структуры могут быть неявно преобразованы к типу заданного интерфейса. Пример:

EditBox editBox = new EditBox(); IControl control = editBox; IDataBound dataBound = editBox;

Если статически неизвестно, реализует ли экземпляр конкретный интерфейс, могут использоваться динамические приведения типов. Например, следующие операторы используют динамические приведения типов для получения реализаций интерфейсов IControl и IDataBound объекта. Поскольку фактическим типом объекта является EditBox, приведения выполняются успешно.

object obj = new EditBox(); IControl control = (IControl)obj; IDataBound dataBound = (IDataBound)obj;

Для описанного выше класса EditBox метод Paint интерфейса IControl и метод Bind интерфейса IDataBound реализуются с использованием членов public. В C# также поддерживается явная реализация членов интерфейса, что позволяет не использовать в классах и структурах члены public. Явная реализация члена интерфейса записывается с использованием полного имени члена интерфейса. Например, класс EditBox может использовать явные реализации членов интерфейса для реализации методов IControl.Paint и IDataBound.Bind следующим образом.

public class EditBox: IControl, IDataBound { void IControl.Paint() {...}

void IDataBound.Bind(Binder b) {...} }

Обращение к явным членам интерфейса осуществляется исключительно посредством типа интерфейса. Например, реализация метода IControl.Paint, предоставляемая описанным выше классом EditBox, может быть вызвана только с предварительным преобразованием ссылки на EditBox к типу интерфейса IControl.

EditBox editBox = new EditBox(); editBox.Paint(); // Error, no such method IControl control = editBox; control.Paint(); // Ok

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

Перечисляемый тип представляет собой тип значений, содержащий конечное число именованных констант. В следующем примере объявляется и используется перечисляемый тип Color, содержащий три постоянных значения: Red, Green и Blue.

using System;

enum Color { Red, Green, Blue }

class Test { static void PrintColor(Color color) { switch (color) { case Color.Red: Console.WriteLine("Red"); break; case Color.Green: Console.WriteLine("Green"); break; case Color.Blue: Console.WriteLine("Blue"); break; default: Console.WriteLine("Unknown color"); break; } }

static void Main() { Color c = Color.Red; PrintColor(c); PrintColor(Color.Blue); } }

Каждый тип перечисления имеет соответствующий целый тип, называемый базовым типом типа перечисления. Если для перечисляемого типа явно не объявлен базовый тип, в качестве базового используется тип int. Формат хранения и диапазон возможных значений перечисляемого типа определяются его базовым типом. Набор значений перечисляемого типа может включать его члены, но не ограничивается только ими. В частности, любое значение базового типа может быть приведено к перечисляемому типу и является отдельным допустимым значением такого типа.

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

enum Alignment: sbyte { Left = -1, Center = 0, Right = 1 }

Как показано в приведенном выше примере, объявление члена перечисляемого типа может включать константное выражение, определяющее значение такого члена. Значение константы для каждого члена должно принадлежать диапазону базового типа. Если в объявлении перечисляемого типа значение не задается явно, первому члену типа присваивается нулевое значение, а каждому последующему члену — значение текстуально предшествующего ему члена, увеличенное на единицу.

Значения перечисляемых типов могут быть преобразованы к значениям целых типов (и наоборот) с помощью приведений типов. Пример:

int i = (int)Color.Blue; // int i = 2; Color c = (Color)2; // Color c = Color.Blue;

В качестве значения по умолчанию для любого перечисляемого типа используется целое нулевое значение, преобразованное к перечисляемому типу. Если переменные автоматически инициализируются с использованием значений по умолчанию, такие значения присваиваются переменным перечисляемого типа. Чтобы обеспечить доступность значений по умолчанию перечисляемого типа, литерал 0 неявно преобразуется к любому перечисляемому типу. Таким образом, допускаются выражения следующего вида.

Color c = 0;

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