在C#中,你能把一个委托的结果链接成另一个的输入吗

本文关键字:结果 链接 输入 另一个 一个 | 更新日期: 2023-09-27 18:19:30

我正在寻找一种方法来链接多个委托,这样一个委托的结果就变成了下一个的输入。我正试图把它用在方程求解程序中,其中的部分是用不同的方法完成的。其想法是,当您构建方程时,程序会添加代理并按特定顺序将其链接,以便正确求解。如果有更好的方法来解决这个问题,请分享。

在C#中,你能把一个委托的结果链接成另一个的输入吗

这可能会有所帮助:

public static Func<T1, TResult> Compose<T1, T2, TResult>(Func<T1, T2> innerFunc, Func<T2, TResult> outerFunc) {
    return arg => outerFunc(innerFunc(arg));
}

这将执行函数组合,运行innerFunc,并在提供初始参数时将结果传递给outerFunc

Func<double, double> floor = Math.Floor;
Func<double, int> convertToInt = Convert.ToInt32;
Func<double, int> floorAndConvertToInt = Compose(floor, convertToInt);
int result = floorAndConvertToInt(5.62);
Func<double, int> floorThenConvertThenAddTen = Compose(floorAndConvertToInt, i => i + 10);
int result2 = floorThenConvertThenAddTen(64.142);

是的,这是可能的-您需要确保委托的返回类型是被调用委托的参数类型。

许多LINQ都是以这种方式构建的,不过您可能需要了解表达式。

您所描述的API类型称为Fluent API。请参阅上一篇文章,以获得一个好的教程。

关于委托链接,请查看.NET 3.5中的LINQ扩展方法,特别是传递给函数的lambda函数(委托)是如何产生IEnumerable结果的,然后该结果可以与另一个扩展方法+lambda链接。

在您的特定情况下,您可能需要创建一个名为Functor的类来接受委托并返回另一个Functor,该Functor也可以由委托操作。

致问候,

使用GetInvocationlist可以实现这一点。

 Delegate[] chain = chained.GetInvocationList();
        int res = 10;
        for( int i = 0; i < chain.Length; i++ ) 
          {
              //Call chain[i]
                res =  chain[i](res);
          }

我自己也在处理一个类似的问题,涉及调用委托序列并将一个委托的输出传递给下一个(等等…),所以我想你可能有兴趣看看我开发的作为概念验证的代码:

static class Program
{
    private static IList<Func<int, int>> delegateList = 
        new List<Func<int, int>>()
    {
        AddOne, AddOne, AddOne, AddOne, AddOne,
        AddOne, AddOne, AddOne, AddOne, AddOne,
    };
    static void Main(string[] args)
    {
        int number = 12;
        Console.WriteLine("Starting number: {0}", number);
        Console.WriteLine("Ending number: {0}", 
                          delegateList.InvokeChainDelegates(number));
        Console.ReadLine();
    }
    public static int AddOne(int num) { return num + 1; }
    public static T InvokeChainDelegates<T>(this IEnumerable<Func<T, T>> source, 
                                            T startValue)
    {
        T result = startValue;
        foreach (Func<T, T> function in source)
        {
            result = function(result);
        }
        return result;
    }
}

序列必须包含相同类型的委托,因此不如已经接受的答案强大,但经过一些调整,这两个代码位可以组合起来提供强大的解决方案。