C#: как создать тип делегата из типов делегата?

Все динамично

"Нет никакого времени компиляции". Все в Python - время выполнения. Модуль 'определяется' путем выполнения источника модуля, от начала до конца, точно так же, как сценарий, и получающееся пространство имен является пространством атрибута модуля. Аналогично, класс 'определяется' путем выполнения тела класса, от начала до конца, и получающееся пространство имен является пространством атрибута класса. Тело класса может содержать абсолютно произвольный код - включая операторов импорта, циклы и другие операторы класса. При создании класса функционируйте или даже модуль 'динамично', относительно как иногда просят, не твердо; на самом деле невозможно избежать, так как все 'динамично'.

5
задан JaysonFix 24 July 2009 в 13:17
поделиться

2 ответа

Вам просто нужно указать конкретные типы. Например:

Func<Func<int, int>, Func<int, int>>

представляет функцию, которая принимает (функция, преобразующая int во второй int) и возвращает (функция, преобразующая int во второй int). Или взять две функции и вернуть третью:

Func<Func<int, int>, Func<int, int>, Func<int, int>>

Например:

Func<Func<int, int>, Func<int, int>> applyTwice = (f => x => f(f(x));

Это может быть возвращено в общем случае методом:

public static Func<Func<T,T>, Func<T,T>> ApplyTwice<T>()
{
    return func => x => func(func(x));
}

Если вы хотите суммировать две функции, вы можете сделать:

public static Func<int, int> Sum(Func<int, int> first, Func<int, int> second)
{
    return x => first(x) + second(x);
}

Теперь, чтобы применить это :

Func<int, int> doubler = x => x * 2;
Func<int, int> squarer = x => x * x;
Func<int, int> doublePlusSquare = Sum(doubler, squarer);

Console.WriteLine(doublePlusSquare(5)); // Prints 35

(Непроверено, но все в порядке ...)


Если у вас нет доступных C # 3 и .NET 3.5, объявите следующих делегатов:

public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);

(Подробнее см. В моем Страница версий C # .)

Затем вам нужно будет использовать анонимные методы, например

public static Func<int, int> Sum(Func<int, int> first, Func<int, int> second)
{
    return delegate(int x) { return first(x) + second(x); };
}

Func<int, int> doubler = delegate (int x) { return x * 2; };
Func<int, int> squarer = delegate (int x) { return x * x; };
Func<int, int> doublePlusSquare = Sum(doubler, squarer);

Console.WriteLine(doublePlusSquare(5)); // Prints 35
14
ответ дан 18 December 2019 в 13:17
поделиться

Как сказал Джон:

Func<int, int> f = i => i * 2;
Func<int, int> g = i => i * i;
Func<int, int> sum = i => f(i) + g(i);

Однако, если вы хотите создать метод Sum для других типов, кроме Func , вам придется использовать

static Func<T, T> Sum<T>(Func<T, T> f, Func<T, T> g)
{
    ParameterExpression p = Expression.Parameter(typeof(T), "i");
    Expression<Func<T, T>> sumExpression =
            Expression.Lambda<Func<T, T>>(
                Expression.Add(
                    Expression.Invoke(Expression.Constant(f), p),
                    Expression.Invoke(Expression.Constant(g), p)),
                p);
    return sumExpression.Compile();
}

Это работает для любого типа T, который определяет оператор «+». Только будьте осторожны со снижением производительности, которое вы получите при компиляции лямбда-выражения.

0
ответ дан 18 December 2019 в 13:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: