C#:如何从委托类型创建委托类型?

时间:2009-07-24 13:17:46

标签: c# delegates

在C#中,如何创建将委托类型映射到委托类型的委托类型? 特别是,在我下面的示例中,我想声明一个委托Sum,使其(借用数学符号)Sum(f,g) = f + g。然后我想调用Sum(f,g) - 例如Sum(f,g)(5) [这意味着f(5) + g(5)]。

class  Example
{
delegate  int  IntToInt  ( int i ) ;

public static int Double ( int i )  { return i * 2 ; }
public static int Square ( int i )  { return i * i ; }

delegate  IntToInt  IntToIntPair_To_IntToInt  ( IntToInt f, IntToInt g ) ;

public static IntToInt Sum ( IntToInt f, IntToInt, g )  { return f + g ; }

public static void Main ( )
    {
    IntToInt  DoubleInstance  =  Double ;
    IntToInt  SquareInstance  =  Square ;

    IntToIntPair_To_IntToInt  SumInstance  =  Sum ;

    System.Console.WriteLine
          ( SumInstance ( DoubleInstance, SquareInstance ) ( 5 ) ) ;
    // should print 35 = 10 + 25 = Double(5) + Square(5)
    }
}

2 个答案:

答案 0 :(得分:14)

您只需要表达具体类型即可。例如:

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# Versions page还有更多内容。)

然后你需要使用匿名方法,例如

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

答案 1 :(得分:0)

像乔恩说的那样:

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

但是,如果你想为Func&lt; int,int&gt;之外的其他类型创建一个Sum方法,你必须使用

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. 请注意编译lambda表达式所带来的性能损失。