Выбери любимый жанр

Выбрать книгу по жанру

Фантастика и фэнтези

Детективы и триллеры

Проза

Любовные романы

Приключения

Детские

Поэзия и драматургия

Старинная литература

Научно-образовательная

Компьютеры и интернет

Справочная литература

Документальная литература

Религия и духовность

Юмор

Дом и семья

Деловая литература

Жанр не определен

Техника

Прочее

Драматургия

Фольклор

Военное дело

Последние комментарии
оксана2018-11-27
Вообще, я больше люблю новинки литератур
К книге
Professor2018-11-27
Очень понравилась книга. Рекомендую!
К книге
Vera.Li2016-02-21
Миленько и простенько, без всяких интриг
К книге
ст.ст.2018-05-15
 И что это было?
К книге
Наталья222018-11-27
Сюжет захватывающий. Все-таки читать кни
К книге

Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю - Страница 235


235
Изменить размер шрифта:

...

}

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

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>  // Возвращает список методов, на которые &quot;указывает&quot; делегат.</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) =&gt; x + y;

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

  }

}

// Program.cs

using System;

using SimpleDelegate;

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

<b>// Создать объект делегата BinaryOp, который</b>

<b>// &quot;указывает&quot; на SimpleMath.Add().</b>