Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лр-2(Классы).docx
Скачиваний:
4
Добавлен:
16.08.2019
Размер:
142.88 Кб
Скачать

Делегаты

Делегат (delegate) — это тип, который позволяет хранить ссылки на функции. Объявляются делегаты во многом так же, как функции, но только безо всякого тела функции и с ключевым словом delegate. В объявлении любого делегата указывается возвращаемый тип и список параметров. После определения делегата можно объявлять переменную с типом этого делегата. Далее эту переменную можно инициализировать как ссылку на любую функцию, которая имеет точно такой же возвращаемый тип и список параметров, как и у делегата. После этого функцию можно вызывать с использованием переменной делегата так, будто бы это и есть сама функция.

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

Применение делегата для вызова функции

001:

002:

003:

004:

005:

006:

007:

008:

009:

010:

011:

012:

013:

014:

015:

016:

017:

018:

019:

020:

021:

022:

023:

024:

025:

026:

027:

028:

029:

030:

031:

032:

033:

034:

035:

class Program

{

delegate double ProcessDelegate (double paraml, double param2);

static double Multiply (double paraml, double param2){

return paraml * param2;

}

static double Divide (double paraml, double param2){

return paraml / param2;

}

static void Main(string[] args){

ProcessDelegate process;

Console.WriteLine("Enter 2 numbers separated with a comma:") ;

// Введите 2 числа, отделив их друг от друга запятой

string input = Console.ReadLine();

int commaPos = input.IndexOf(',');

double paraml = Convert.ToDouble(input.Substring(0, commaPos));

double param2 = Convert.ToDouble(input.Substring(commaPos + 1, input.Length - commaPos - 1)) ;

Console. WriteLine ("Enter M to multiply or D to divide:") ;

// Введите М, если хотите выполнить операцию умножения,

// или D, если операцию деления

input = Console.ReadLine();

if (input == "M")

process = new ProcessDelegate(Multiply);

else

process = new ProcessDelegate(Divide);

Console.WriteLine("Result: {0}", process(paraml, param2));

// Вывод результата

Console.ReadKey();

}

Классы Определение классов в с#

В языке С# для определения классов применяется ключевое слово class:

class MyClass

{

// Члены класса.

}

В этом коде определяется класс по имени MyClass. После определения класса его экземпляр можно создавать в любом месте проекта, где имеется доступ к этому определению. По умолчанию классы объявляются внутренними, что делает их доступными только для кода, который находится внутри текущего проекта. Объявлять их таковыми можно явно с использованием ключевого слова internal, как показано ниже:

internal class MyClass

{

// Члены класса.

}

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

public class MyClass

{

// Члены класса.

}

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

Помимо этих двух ключевых слов, играющих роль модификаторов доступа, можно использовать либо ключевое слово abstract и тем самым делать класс абстрактным (т.е. не допускающим создания экземпляров, позволяющим только наследовать от него другие классы и способным иметь абстрактные члены), либо ключевое слово sealed и тем самым сделать класс герметизированным (не допускающим наследования от него никаких других классов). Эти два ключевых слова являются взаимно исключающими, т.е. указывать можно только какое-то одно из них. В частности, абстрактный класс объявляется следующим образом:

public abstract class MyClass

{

// Члены класса, могут быть и абстрактными.

}

абстрактный здесь MyClass представляет собой общедоступный класс, хотя внутренние абстрактные классы тоже допускается создавать.

Герметизированные классы объявляются следующим образом:

public sealed class MyClass

{

// Члены класса.

}

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

Наследование тоже может задаваться в определении класса. Делается это добавлением после имени класса двоеточия со следующим за ним именем базового класса, как показано ниже:

public class MyClass : MyBase

{

}

В определениях классов разрешено указывать только один базовый класс и в случае наследования от абстрактного класса нужно обязательно реализовать все наследуемые абстрактные члены (если только производный класс тоже не является абстрактным).

Компилятор не допускает, чтобы производный класс был более доступным, чем его базовый класс. Это означает, что внутренний класс может наследоваться от общедоступного класса, а вот общедоступный класс от внутреннего базового — нет. То есть следующий код является допустимым:

public class MyBase

// Члены класса.

}

internal class MyClass : MyBase

{

// Члены класса.

}

А приведенный ниже код скомпилировать не удастся:

internal class MyBase

{

// Члены класса.

}

public class MyClass : MyBase

{

// Члены класса.

}

Если базовый класс не используется, класс наследуется только от базового класса System.Object (который в С# имеет псевдоним object). В конечном счете, класс System.Object является корневым в иерархии наследования абсолютно всех классов.

Помимо базовых классов подобным образом после двоеточия могут также указываться и поддерживаемые интерфейсы. Если специфицируется базовый класс, он должен указываться после двоеточия первым, а интерфейсы — уже за ним. Если же никакого базового класса не задано, тогда интерфейсы указываются сразу же после двоеточия. Для разделения имен базового класса (если таковой задан) и интерфейсов служат запятые.

Допустимые комбинации модификаторов доступа для определений классов

Модификатор

Значение

Отсутствует или internal

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

public

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

abstract или internal abstract

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

public abstract

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

sealed или internal sealed

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

public sealed

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

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