Шрифт:
Интервал:
Закладка:
...
}
Делегаты могут также "указывать" на методы, которые содержат любое количество параметров out и ref (а также параметры типа массивов, помеченные с помощью ключевого слова params). Пусть имеется следующий тип делегата:
public delegate string MyOtherDelegate(out bool a, ref bool b, int c);
Сигнатура метода Invoke() выглядит вполне ожидаемо.
Подводя итоги, отметим, что определение типа делегата C# дает в результате запечатанный класс со сгенерированным компилятором методом, в котором типы параметров и возвращаемые типы основаны на объявлении делегата. Базовый шаблон может быть приближенно описан с помощью следующего псевдокода:
// Это лишь псевдокод!
public sealed class <i>ИмяДелегата</i> : System.MulticastDelegate
{
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})public <i>возвращаемоеЗначениеДелегата</i>
Invoke(<i>всеВходныеRefиOutПараметрыДелегата</i>);
}
Базовые классы System.MulticastDelegate и System.Delegate
Итак, когда вы строите тип с применением ключевого слова delegate, то неявно объявляете тип класса, производного от System.MulticastDelegate. Данный класс предоставляет своим наследникам доступ к списку, который содержит адреса методов, поддерживаемых типом делегата, а также несколько дополнительных методов (и перегруженных операций) для взаимодействия со списком вызовов. Ниже приведены избранные методы класса System.MulticastDelegate:
public abstract class MulticastDelegate : Delegate
{
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})<b> // Возвращает список методов, на которые "указывает" делегат.</b>
public sealed override Delegate[] GetInvocationList();
<b> // Перегруженные операции.</b>
public static bool operator ==
(MulticastDelegate d1, MulticastDelegate d2);
public static bool operator !=
(MulticastDelegate d1, MulticastDelegate d2);
<b> // Используются внутренне для управления списком методов,</b>
<b> // поддерживаемых делегатом.</b>
private IntPtr _invocationCount;
private object _invocationList;
}
Класс System.MulticastDelegate получает дополнительную функциональность от своего родительского класса System.Delegate. Вот фрагмент его определения:
public abstract class Delegate : ICloneable, ISerializable
{
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})<b> // Методы для взаимодействия со списком функций.</b>
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);
<b> // Перегруженные операции.</b>
public static bool operator ==(Delegate d1, Delegate d2);
public static bool operator !=(Delegate d1, Delegate d2);
<b> // Свойства, открывающие доступ к цели делегата.</b>
public MethodInfo Method { get; }
public object Target { get; }
}
Имейте в виду, что вы никогда не сможете напрямую наследовать от таких базовых классов в своем коде (попытка наследования приводит к ошибке на этапе компиляции). Тем не менее, когда вы используете ключевое слово delegate, то тем самым неявно создаете класс, который "является" MulticastDelegate. В табл. 12.1 описаны основные члены, общие для всех типов делегатов.
Пример простейшего делегата
На первый взгляд делегаты могут показаться несколько запутанными. Рассмотрим для начала простой проект консольного приложения (по имени SimpleDelegate), в котором применяется определенный ранее тип делегата BinaryOp. Ниже показан полный код с последующим анализом:
// SimpleMath.cs
namespace SimpleDelegate
{
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})// Этот класс содержит методы, на которые
// будет указывать 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");
<b>// Создать объект делегата BinaryOp, который</b>
<b>// "указывает" на SimpleMath.Add().</b>
- Понимание SQL - Мартин Грубер - Базы данных