Делегаты, лямбды в C# и UniRx

Что такое делегаты и сигнатура

  • Делегат – это указатель на метод. С помощью него из любого места в коде можно вызвать указанный метод.

  • Сигнатура метода – возвращаемый тип, и список типов всех аргументов этого метода.

Например, метод выше имеет сигнатуру “void, int, string”
  • Делегаты различаются между собой именно по сигнатуре методов, на которые они могут указывать.

Использование делегатов

  • Делегаты можно использовать в качестве типов переменных, если объявить их сигнатуру и имя

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

  • Делегаты так же как и обычные переменные можно передавать в методы и хранить в классах и т.д.

  • Определенный тип делегата поддерживает любые методы с такой же сигнатурой

Анонимные методы и лямбды

  • Методы, которые не имеют представления в классе, а сразу создают экземпляр объекта в методе называются анонимными

  • Существует краткая запись анонимных методов, которые зовутся лямбда выражениями

  • (arg1, arg2) => arg1 + arg2 – лямбда выражение, которое можно использовать вместо метода Plus из предыдущего примера

Лямбды можно записывать по разному:

  • (arg1, arg2) => arg1 + arg2

  • () => CallSomeMethod()

  • () => { int result = CallSomeMethod(); return result; }

Action, Func, Predicate

  • В C# существуют унифицированные делегаты, которые можно сразу использовать (записывая как типы), не объявляя их

  • Action<arg1, arg2, …> - возвращает void, может принимать сколько угодно аргументов

  • Func<arg1, arg2, …, returnType> - возвращает returnType (стоит всегда в конце), принимает сколько угодно аргументов

  • Predicate - возвращает bool, принимает лишь 1 аргумент. Используется в большинстве случаев как фильтр, например в LINQ в методе Where, по факту является математическим предикатом

Переделка примера под лямбды и Func

Полезные методы в UniRx

  • TimerFrame(int frames) – Создает покадровый таймер

  • TakeUntilDestroy(GameObject/Component target) – Уничтожает таймер, если уничтожен данный объект/компонент

  • TakeUntilDisable(GameObject/Component target) – То же самое, но при выключении

  • TakeWhile(Func<long, bool> predicate) – Таймер остановится, когда предикат выдаст false

  • SkipUntil(IObservable timer) – Таймер не будет обрабатываться, пока внутренний таймер не окончится

  • SkipWhile(Func<T, bool> predicate) – Таймер не будет обрабатыватся, пока предикат выдает true

  • Finally(Action action) – Выполняет action когда таймер кончается или вообще уничтожается

  • Interval(TimeSpan period) – Повторяющийся таймер с указанным периудом

  • IntervalFrame(int frameCount, FrameCountType type) – Тоже самое, но по кадрам, можно указать на какие типы тиков ориетироватся (Update/FixedUpdate/EndOfFrame)

Примеры таймеров

  • Перемещение объекта к точке с заданной скоростью

  • Вызов какого-либо действия раз в секунду, когда объект вблизи точки на 2 метра, и пока он существует

Last updated