Введение в C#: классы

Информация - Компьютеры, программирование

Другие материалы по предмету Компьютеры, программирование

double width, double height)

{

this.width = width;

this.height = height;

}

public double Square()

{

return (width * height);

}

}

class CCircle: CShape, IShape

{

double radius;

public CCircle(double radius)

{

this.radius = radius;

}

public double Square()

{

return (Math.PI * radius * radius);

}

}

class Example_3

{

public static void Main()

{

CRectangle rect = new CRectangle(3, 4);

CCircle circ = new CCircle(5);

Console.WriteLine(rect.Square());

Console.WriteLine(circ.Square());

}

}

Оба объекта, rect и circ, являются производными от базового класса CShape и тем самым они наследуют единственный метод IsShape(). Задав имя интерфейса IShape в объявлениях CRectangle и CCircle, мы указываем на то, что в данных классах содержится реализация всех методов интерфейса IShape. Кроме того, члены интерфейсов не имеют модификаторов доступа. Их область видимости определяется непосредственно реализующим классом.

Свойства

Рассматривая классы языка C#, просто нельзя обойти такое новшество, как свойства (properties). Надо сказать, что здесь чувствуется влияние языков Object Pascal и Java, в которых свойства всегда являлись неотъемлемой частью классов. Что же представляют собой эти самые свойства? С точки зрения пользователя, свойства выглядят практически так же, как и обычные поля класса. Им можно присваивать некоторые значения и получать их обратно. В то же время свойства имеют бо,льшую функциональность, так как чтение и изменение их значений выполняется с помощью специальных методов класса. Такой подход позволяет изолировать пользовательскую модель класса от ее реализации. Поясним данное определение на конкретном примере:

using System;

using System.Runtime.InteropServices;

class Screen

{

[DllImport(”kernel32.dll”)]

static extern bool SetConsoleTextAttribute(

int hConsoleOutput, ushort wAttributes

);

[DllImport(”kernel32.dll”)]

static extern int GetStdHandle(

uint nStdHandle

);

const uint STD_OUTPUT_HANDLE = 0x0FFFFFFF5;

static Screen()

{

output_handle = GetStdHandle(STD_OUTPUT_HANDLE);

m_attributes = 7;

}

public static void PrintString(string str)

{

Console.Write(str);

}

public static ushort Attributes

{

get

{

return m_attributes;

}

set

{

m_attributes = value;

SetConsoleTextAttribute(output_handle, value);

}

}

private static ushort m_attributes;

private static int output_handle;

}

class Example_4

{

public static void Main()

{

for (ushort i = 1; i < 8; i++)

{

Screen.Attributes = i;

Screen.PrintString(”Property Demo

”);

}

}

}

Программа выводит сообщение Property Demo, используя различные цвета символов (от темно-синего до белого). Давайте попробуем разобраться в том, как она работает. Итак, сначала мы импортируем важные для нас функции API-интерфейса Windows: SetConsoleTextAttribute и GetStdHandle. К сожалению, стандартный класс среды .NET под названием Console не имеет средств управления цветом вывода текстовой информации. Надо полагать, что корпорация Microsoft в будущем все-таки решит эту проблему. Пока же для этих целей придется воспользоваться службой вызова платформы PInvoke (обратите внимание на использование атрибута DllImport). Далее, в конструкторе класса Screen мы получаем стандартный дескриптор потока вывода консольного приложения и помещаем его значение в закрытую переменную output_handle для дальнейшего использования функцией SetConsoleTextAttribute. Кроме этого, мы присваиваем другой переменной m_attributes начальное значение атрибутов экрана (7 соответствует белому цвету символов на черном фоне). Заметим, что в реальных условиях стоило бы получить текущие атрибуты экрана с помощью функции GetConsoleScreenBufferInfo из набора API-интерфейса Windows. В нашем же случае это несколько усложнило бы пример и отвлекло от основной темы.

В классе Screen мы объявили свойство Attributes, для которого определили функцию чтения (getter) и функцию записи (setter). Функция чтения не выполняет каких-либо специфических действий и просто возвращает значение поля m_attributes (в реальной программе она должна бы возвращать значение атрибутов, полученное с помощью все той же GetConsoleScreenBufferInfo). Функция записи несколько сложнее, так как кроме тривиального обновления значения m_attributes она вызывает функцию SetConsoleTextAttribute, устанавливая заданные атрибуты функций вывода текста. Значение устанавливаемых атрибутов передается специальной переменной value. Обратите внимание на то, что поле m_attributes является закрытым, а стало быть, оно не может быть доступно вне класса Screen. Единственным способом чтения и/или изменения этого метода является свойство Attributes.

Свойства позволяют не только возвращать и изменять значение внутренней переменной класса, но и выполнять дополнительные функции. Так, они позволяют произвести проверку значения или выполнить иные действия, как показано в вышеприведенном примере.

В языке C# свойства реализованы на уровне синтаксиса. Более того, рекомендуется вообще не использовать открытых полей классов. На первый взгляд, при таком подходе теряется эффективность из-за того, что операции присваивания будут заменены вызовами функций getter и setter. Отнюдь! Среда .NET сгенерирует для них соответствующий inline-код.

Делегаты

Язык программирования C# хотя и допускает, но все же не поощряет использование указателей. В некоторых ситуациях бывает особенно трудно обойтись без указателей на функции. Для этих целей в C# реализованы так называемые делегаты (delegates), которые иногда еще называют безопасными аналогами указателей на функцию. Ниже приведен простейший пример использования метода-делегата:

using System;

delegate void MyDelegate();

class Example_5

{

static void Func()

{

System.Console.WriteLine(MyDelegate.Func());

}

public static void Main()

{

MyDelegate f = new MyDelegate(Func);

f();

}

}

Помимо того что делегаты обеспечивают типовую защищенность, а следовательно, и повышают безопасность кода, они отл?/p>