Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

sealed class BinaryOp : System.MulticastDelegate

{

public int Invoke(int x, int y);

...

}

Первым делом обратите внимание, что параметры и возвращаемый тип для метода

Invoke
в точности соответствуют определению делегата
BinaryOp
.

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

string
и принимающий три входных параметра типа
System.Boolean
:

public delegate string MyDelegate (bool a, bool b, bool c);

На этот раз сгенерированный компилятором класс можно представить так:

sealed class MyDelegate : System.MulticastDelegate

{

public string Invoke(bool a, bool b, bool c);

...

}

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

out
и
ref
(а также параметры типа массивов, помеченные с помощью ключевого слова
params
). Пусть имеется следующий тип делегата:

public delegate string MyOtherDelegate(out bool a, ref bool b, int c);

Сигнатура метода

Invoke
выглядит вполне ожидаемо.

Подводя итоги, отметим, что определение типа делегата C# дает в результате запечатанный класс со сгенерированным компилятором методом, в котором типы параметров и возвращаемые типы основаны на объявлении делегата. Базовый шаблон может быть приближенно описан с помощью следующего псевдокода:

// Это лишь псевдокод!

public sealed class ИмяДелегата : System.MulticastDelegate

{

public возвращаемоеЗначениеДелегата

Invoke(всеВходныеRefиOutПараметрыДелегата);

}

Базовые классы System.MulticastDelegate и System.Delegate

Итак, когда вы строите тип с применением ключевого слова

delegate
, то неявно объявляете тип класса, производного от
System.MulticastDelegate
. Данный класс предоставляет своим наследникам доступ к списку, который содержит адреса методов, поддерживаемых типом делегата, а также несколько дополнительных методов (и перегруженных операций) для взаимодействия со списком вызовов. Ниже приведены избранные методы класса
System.MulticastDelegate
:

public abstract class MulticastDelegate : Delegate

{

// Возвращает список методов, на которые "указывает" делегат.

public sealed override Delegate[] GetInvocationList;

// Перегруженные операции.

public static bool operator ==

(MulticastDelegate d1, MulticastDelegate d2);

public static bool operator !=

(MulticastDelegate d1, MulticastDelegate d2);

//
Используются внутренне для управления списком методов,

// поддерживаемых делегатом.

private IntPtr _invocationCount;

private object _invocationList;

}

Класс

System.MulticastDelegate
получает дополнительную функциональность от своего родительского класса
System.Delegate
. Вот фрагмент его определения:

public abstract class Delegate : ICloneable, ISerializable

{

// Методы для взаимодействия со списком функций.

public static Delegate Combine(params Delegate[] delegates);

public static Delegate Combine(Delegate a, Delegate b);

public static Delegate Remove(

Delegate source, Delegate value);

public static Delegate RemoveAll(

Delegate source, Delegate value);

// Перегруженные операции.

public static bool operator ==(Delegate d1, Delegate d2);

public static bool operator !=(Delegate d1, Delegate d2);

// Свойства, открывающие доступ к цели делегата.

public MethodInfo Method { get; }

public object Target { get; }

}

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

delegate
, то тем самым неявно создаете класс, который "является"
MulticastDelegate
. В табл. 12.1 описаны основные члены, общие для всех типов делегатов.

Пример простейшего делегата

На первый взгляд делегаты могут показаться несколько запутанными. Рассмотрим для начала простой проект консольного приложения (по имени

SimpleDelegate
), в котором применяется определенный ранее тип делегата
BinaryOp
. Ниже показан полный код с последующим анализом:

// SimpleMath.cs

namespace SimpleDelegate

{

// Этот класс содержит методы, на которые

// будет указывать BinaryOp.

public class SimpleMath

{

public static int Add(int x, int y) => x + y;

public static int Subtract(int x, int y) => x - y;

}

}

// Program.cs

using System;

using SimpleDelegate;

Console.WriteLine("***** Simple Delegate Example *****\n");

Поделиться с друзьями: