Язык программирования C#9 и платформа .NET5
Console.WriteLine("The size of int is {0}.", sizeof(int));Console.WriteLine("The size of long is {0}.", sizeof(long));}Тем не менее, если вы хотите получить размер специальной структуры
, то методPointпридется модифицировать (обратите внимание на добавление ключевого словаUseSizeOfOperator()):unsafeunsafe static void UseSizeOfOperator(){...unsafe {Console.WriteLine("The size of Point is {0}.", sizeof(Point));}}Итак, обзор нескольких более сложных средств языка программирования C# завершен. Напоследок снова необходимо отметить, что в большинстве проектов .NET эти средства могут вообще не понадобиться (особенно указатели). Тем не менее, как будет показано в последующих главах, некоторые средства действительно полезны (и даже обязательны) при работе с API-интерфейсами LINQ, в частности расширяющие методы и анонимные типы.
Резюме
Целью главы было углубление знаний языка программирования С#. Первым делом мы исследовали разнообразные более сложные конструкции в типах (индексаторные методы, перегруженные операции и специальные процедуры преобразования).
Затем мы рассмотрели роль расширяющих методов и анонимных типов. Как вы увидите в главе 13, эти средства удобны при работе с API-интерфейсами LINQ (хотя при желании их можно применять в коде повсеместно). Вспомните, что анонимные методы позволяют быстро моделировать "форму" типа, в то время как расширяющие методы дают возможность добавлять новую функциональность к типам без необходимости в определении подклассов.
Финальная часть главы была посвящена небольшому набору менее известных ключевых слов (
,sizeofи т.п.); наряду с ними рассматривалась работа с низкоуровневыми типами указателей. Как было установлено в процессе исследования типов указателей, в большинстве приложений C# их никогда не придется использовать.unsafeГлава 12
Делегаты, события и лямбда-выражения
Вплоть до настоящего момента в большинстве разработанных приложений к операторам верхнего уровня внутри файла
добавлялись разнообразные порции кода, тем или иным способом отправляющие запросы к заданному объекту. Однако многие приложения требуют, чтобы объект имел возможность обращаться обратно к сущности, которая его создала, используя механизм обратного вызова. Хотя механизмы обратного вызова могут применяться в любом приложении, они особенно важны в графических пользовательских интерфейсах, где элементы управления (такие как кнопки) нуждаются в вызове внешних методов при надлежащих обстоятельствах (когда произведен щелчок на кнопке, курсор мыши наведен на поверхность кнопки и т.д.).Program.csВ рамках платформы .NET Core предпочтительным средством определения и реагирования на обратные вызовы в приложении является тип делегата. По существу тип делегата .NET Core — это безопасный в отношении типов объект, "указывающий" на метод или список методов, которые могут быть вызваны позднее. Тем не менее, в отличие от традиционного указателя на функцию C++ делегаты представляют собой классы, которые обладают встроенной поддержкой группового и асинхронного вызова методов.
На заметку! В предшествующих версиях .NET делегаты обеспечивали вызов асинхронных методов с помощью
. Хотя компилятор по-прежнему генерирует методыBeginInvoke()/EndInvoke(), в .NET Core они не поддерживаются. Причина в том, что шаблон сBeginInvoke()/EndInvoke()иIAsyncResult, используемый делегатами, был заменен асинхронным шаблоном на основе задач. Асинхронное выполнение подробно обсуждается в главе 15.BeginInvoke()/EndInvoke()В текущей главе вы узнаете, каким образом создавать и манипулировать типами делегатов, а также использовать ключевое слово event языка С#, которое облегчает работу с типами делегатов. По ходу дела вы также изучите несколько языковых средств С#, ориентированных на делегаты и события, в том числе анонимные методы и групповые преобразования методов.
Глава завершается исследованием лямбда-выражений. С помощью лямбда-операции C# (
) можно указывать блок операторов кода (и подлежащие передаче им параметры) везде, где требуется строго типизированный делегат. Как будет показано, лямбда-выражение — не более чем замаскированный анонимный метод и является упрощенным подходом к работе с делегатами. Вдобавок та же самая операция (в .NEТ Framework 4.6 и последующих версиях) может применяться для реализации метода или свойства, содержащего единственный оператор, посредством лаконичного синтаксиса.=>Понятие типа делегата
Прежде чем формально определить делегаты, давайте ненадолго оглянемся назад. Исторически сложилось так, что в API-интерфейсе Windows часто использовались указатели на функции в стиле С для создания сущностей под названием функции обратного вызова или просто обратные вызовы. С помощью обратных вызовов программисты могли конфигурировать одну функцию так, чтобы она обращалась к другой функции в приложении (т.е. делала обратный вызов). С применением такого подхода разработчики Windows-приложений имели возможность обрабатывать щелчки на кнопках, перемещение курсора мыши, выбор пунктов меню и общие двусторонние коммуникации между двумя сущностями в памяти.
В .NET и .NET Core обратные вызовы выполняются в безопасной в отношении типов объектно-ориентированной манере с использованием делегатов. Делегат — это безопасный в отношении типов объект, указывающий на другой метод или возможно на список методов приложения, которые могут быть вызваны в более позднее время.
В частности, делегат поддерживает три важных порции информации:
• адрес метода, вызовы которого он делает:
• аргументы (если есть) вызываемого метода:
• возвращаемое значение (если есть) вызываемого метода.
На заметку! Делегаты .NET Core могут указывать либо на статические методы, либо на методы экземпляра.
После того как делегат создан и снабжен необходимой информацией, он может во время выполнения динамически вызывать метод или методы, на которые указывает.
Определение типа делегата в C#
Для определения типа делегата в языке C# применяется ключевое слово
. Имя типа делегата может быть любым желаемым. Однако сигнатура определяемого делегата должна совпадать с сигнатурой метода или методов, на которые он будет указывать. Например, приведенный ниже тип делегата (по имениdelegate) может указывать на любой метод, который возвращает целое число и принимает два целых числа в качестве входных параметров (позже в главе вы самостоятельно построите такой делегат, а пока он представлен лишь кратко):BinaryOp