Язык программирования C#9 и платформа .NET5
Часть 234 из 642 Информация о книге
// Этот делегат может указывать на любой метод, который принимает// два целочисленных значения и возвращает целочисленное значение.public delegate int BinaryOp(int x, int y);Когда компилятор C# обрабатывает тип делегата, он автоматически генерирует запечатанный (
) класс, производный отsealed. Этот класс (в сочетании со своим базовым классомSystem.MulticastDelegate) предоставляет необходимую инфраструктуру для делегата, которая позволяет хранить список методов, подлежащих вызову в будущем. Например, если вы изучите делегатSystem.Delegateс помощью утилитыBinaryOp, то обнаружите показанные ниже детали (вскоре вы построите полный пример):ildasm.exe// -------------------------------------------------------// TypDefName: SimpleDelegate.BinaryOp// Extends : System.MulticastDelegate// Method #1// -------------------------------------------------------// MethodName: .ctor// ReturnType: Void// 2 Arguments// Argument #1: Object// Argument #2: I// Method #2// -------------------------------------------------------// MethodName: Invoke// ReturnType: I4// 2 Arguments// Argument #1: I4// Argument #2: I4// 2 Parameters// (1) ParamToken : Name : x flags: [none]// (2) ParamToken : Name : y flags: [none] //// Method #3// -------------------------------------------------------// MethodName: BeginInvoke// ReturnType: Class System.IAsyncResult// 4 Arguments// Argument #1: I4// Argument #2: I4// Argument #3: Class System.AsyncCallback// Argument #4: Object// 4 Parameters// (1) ParamToken : Name : x flags: [none]// (2) ParamToken : Name : y flags: [none]// (3) ParamToken : Name : callback flags: [none]// (4) ParamToken : Name : object flags: [none]//// Method #4// -------------------------------------------------------// MethodName: EndInvoke// ReturnType: I4 (int32)// 1 Arguments// Argument #1: Class System.IAsyncResult// 1 Parameters// (1) ParamToken : Name : result flags: [none]Как видите, в сгенерированном компилятором классе
определены три открытых метода. Главным методом в .NET Core являетсяBinaryOp, т.к. он используется для вызова каждого метода, поддерживаемого объектом делегата, в синхронной манере; это означает, что вызывающий код должен ожидать завершения вызова, прежде чем продолжить свою работу. Довольно странно, но синхронный методInvoke()может не нуждаться в явном вызове внутри вашего кода С#. Вскоре будет показано, чтоInvoke()вызывается "за кулисами", когда вы применяете соответствующий синтаксис С#.Invoke()На заметку! Несмотря на то что методы
иBeginInvoke()генерируются, они не поддерживаются при запуске вашего кода под управлением .NET Core. Это может разочаровывать, поскольку в случае их использования вы получите ошибку не на этапе компиляции, а во время выполнения.EndInvoke()Так благодаря чему же компилятор знает, как определять метод
? Для понимания процесса ниже приведен код сгенерированного компилятором классаInvoke()(полужирным курсивом выделены элементы, указанные в определении типа делегата):BinaryOpsealed class <b>BinaryOp</b> : System.MulticastDelegate{public <b>int</b> Invoke(<b>int x, int y</b>);...}Первым делом обратите внимание, что параметры и возвращаемый тип для метода
в точности соответствуют определению делегатаInvoke().BinaryOpДавайте рассмотрим еще один пример. Предположим, что определен тип делегата, который может указывать на любой метод, возвращающий значение
и принимающий три входных параметра типаstring:System.Booleanpublic delegate string MyDelegate (bool a, bool b, bool c);На этот раз сгенерированный компилятором класс можно представить так:
sealed class <b>MyDelegate</b> : System.MulticastDelegate{public <b>string</b> Invoke(<b>bool a, bool b, bool c</b>);