Шрифт:
Интервал:
Закладка:
c1.AboutToBlow += delegate(object sender, CarEventArgs e)
{
Console.WriteLine("Critical Message from Car: {0}", e.msg);
};
Доступ к локальным переменным
Анонимные методы интересны тем, что способны обращаться к локальным переменным метода, где они определены. Формально такие переменные называются внешними переменными анонимного метода. Ниже перечислены важные моменты, касающиеся взаимодействия между областью действия анонимного метода и областью действия метода, в котором он определен.
• Анонимный метод не имеет доступа к параметрам ref и out определяющего метода.
• Анонимный метод не может иметь локальную переменную, имя которой совпадает с именем локальной переменной внешнего метода.
• Анонимный метод может обращаться к переменным экземпляра (или статическим переменным) из области действия внешнего класса.
• Анонимный метод может объявлять локальную переменную с тем же именем, что и у переменной-члена внешнего класса (локальные переменные имеют отдельную область действия и скрывают переменные-члены из внешнего класса).
Предположим, что в операторах верхнего уровня определена локальная переменная по имени aboutToBlowCounter типа int. Внутри анонимных методов, которые обрабатывают событие AboutToBlow, выполните увеличение значения aboutToBlowCounter на 1 и вывод результата на консоль перед завершением операторов:
Console.WriteLine("***** Anonymous Methods *****n");
int aboutToBlowCounter = 0;
// Создать объект Car обычным образом.
Car c1 = new Car("SlugBug", 100, 10);
// Зарегистрировать обработчики событий как анонимные методы.
c1.AboutToBlow += delegate
{
<b> aboutToBlowCounter++;</b>
Console.WriteLine("Eek! Going too fast!");
};
c1.AboutToBlow += delegate(object sender, CarEventArgs e)
{
<b> aboutToBlowCounter++;</b>
Console.WriteLine("Critical Message from Car: {0}", e.msg);
};
...
// В конце концов, это будет инициировать события.
for (int i = 0; i < 6; i++)
{
c1.Accelerate(20);
}
Console.WriteLine("AboutToBlow event was fired {0} times.",
aboutToBlowCounter);
Console.ReadLine();
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})После запуска модифицированного кода вы обнаружите, что финальный вывод Console.WriteLine() сообщает о двукратном инициировании события AboutToBlow.
Использование ключевого слова static с анонимными методами (нововведение в версии 9.0)
В предыдущем примере демонстрировались анонимные методы, которые взаимодействовали с переменными, объявленными вне области действия самих методов. Хотя возможно именно это входило в ваши намерения, прием нарушает инкапсуляцию и может привести к нежелательным побочным эффектам в программе. Вспомните из главы 4, что локальные функции могут быть изолированы от содержащего их кода за счет их настройки как статических, например:
static int AddWrapperWithStatic(int x, int y)
{
// Выполнить проверку достоверности
return Add(x,y);
static int Add(int x, int y)
{
return x + y;
}
}
В версии C# 9.0 анонимные методы также могут быть помечены как статические с целью предохранения инкапсуляции и гарантирования того, что они не привнесут какие-либо побочные эффекты в код, где они содержатся. Вот как выглядит модифицированный анонимный метод:
c1.AboutToBlow += static delegate
{
// Этот код приводит к ошибке на этапе компиляции,
// потому что анонимный метод помечен как статический
aboutToBlowCounter++;
Console.WriteLine("Eek! Going too fast!");
};
Предыдущий код не скомпилируется из-за попытки анонимного метода получить доступ к переменной, объявленной вне области его действия.
Использование отбрасывания с анонимными методами (нововведение в версии 9.0)
Отбрасывание, представленное в главе 3, в версии C# 9.0 было обновлено с целью применения в качестве входных параметров, но с одной уловкой. Поскольку символ подчеркивания (_) в предшествующих версиях C# считался законным идентификатором переменной, в анонимном методе должно присутствовать два и более подчеркиваний, чтобы они трактовались как отбрасывание.
Например, в следующем коде создается делегат Func<>, который принимает два целых числа и возвращает еще одно целое число. Приведенная реализация игнорирует любые переданные переменные и возвращает значение 42:
Console.WriteLine("******** Discards with Anonymous Methods ********");
Func<int,int,int> constant = delegate (int _, int _) {return 42;};
Console.WriteLine("constant(3,4)={0}",constant(3,4));
Понятие лямбда-выражений
Чтобы завершить знакомство с архитектурой событий .NET Core, необходимо исследовать лямбда-выражения. Как объяснялось ранее в главе, язык C# поддерживает возможность обработки событий "встраиваемым образом", позволяя назначать блок операторов кода прямо событию с применением анонимных методов вместо построения отдельного метода, который должен вызываться делегатом. Лямбда-выражения всего лишь лаконичный способ записи анонимных методов, который в конечном итоге упрощает работу с типами делегатов .NET Core.
- Понимание SQL - Мартин Грубер - Базы данных