Страницы

Поиск по вопросам

четверг, 12 декабря 2019 г.

Зачем нужен встроенный делегат Func?

#c_sharp


При решении очередной проблемы опять сталкнулся со встроенным делегатом Func. Никак
не могу понять его предназначение, как он работает и как устроен. Может кто-то на каком-то
простом примере объяснить что это, для чего используется, как это работает и как этим
пользоваться?
    


Ответы

Ответ 1



Допустим мы имеем метод, который рисует графики различных функций, для простоты - алгебраических, вида y=f(x). Нашему методу все равно какую именно функцию данного вида рисовать, главное чтобы вид функции совпадал с заданным. тогда мы можем определить наш метод следующим образом: public void DrawFunc(Func f) { for(double x = 0.0; x<1.0; x+=0.001) { double y = f(x); //и далее рисуем точки графика } } Теперь для отрисовки графика нам нужно вызвать наш метод и передать ему подходящую функцию. Для Func< double, double> нам подойдет любая функция вида double FuncName(double ParamName), например Math.Sin. Вызов будет выглядеть так: DrawFunc(Math.Sin); Данный делегат, как и аналогичный ему Action используется в основном для быстрого объявления делегатов стандартного вида. Определено несколько отдельных делегатов вида Func< T1,...,T16,TResult>, и Action< T1,...,T16> которые могут принимать до 16-ти параметров (.NET 4+, до 4-х для .NET 3.5), типы которых указываются при объявлении. Кроме этого для Func необходимо указать тип возвращаемого значения TResult, у Action возвращаемое значение всегда void. Больше ничем от обычных делегатов они не отличаются. тут уже обсуждалась очень похожая тема и есть еще немного информации

Ответ 2



В дополнение к правильному ответу @rdorn: Func<> — это по существу (с мелкими отличиями) тип, описывающий функцию. Вы можете передавать в другой метод или класс не только данные, но и код. Для этого вам нужно описать его тип, чтобы его можно было присваивать параметру, записывать в переменные или возвращать из функций. Вот Func<> именно для этого и служит. Пример: // применяет функцию дважды к начальному значению и выводит результат void ApplyTwiceAndPrint(Func f, int value) { int result1 = f(value); int result2 = f(result1); Console.WriteLine(result2); } ApplyTwiceAndPrint(n => n * n, 3); // выводит 81 Как именно это работает внутри? Внутри Func<...> является объектом типа MulticastDelegate, у которого определена функция Invoke(...). Когда вы пишете f(value), компилятор поставляет вместо этого f.Invoke(value), то есть, вызывает метод Invoke. (Да, тут есть немного компиляторного «сахара», которого нету, скажем, у Java.) Внутри объект типа MulticastDelegate хитрым системно-зависимым образом содержит по сути указатель на метод, который и будет вызван в реализации метода Invoke.

Комментариев нет:

Отправить комментарий