您能否在 C# 中将一个委托的结果链接为另一个委托的输入?

发布于 2024-12-24 02:28:16 字数 136 浏览 1 评论 0原文

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

I am looking for a way to chain several delegates so the result from one becomes the input of the next. I am trying to use this in equation solving program where portions are done by different methods. The idea is that when you are building the equation the program adds the delegates and chains them in a particular order, so it can be solved properly. If there is a better way to approach the problem please share.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

烟若柳尘 2024-12-31 02:28:16

这可能会有所帮助:

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);

This might help:

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

This performs function composition, running innerFunc and passing the result to outerFunc when the initial argument is supplied:

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);
夜空下最亮的亮点 2024-12-31 02:28:16

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

很多 LINQ 都是以这种方式构建的,尽管您可能想看看表达式

Yes this is possible - you need to ensure that the return type of the delegate is one that is the parameter type of the delegate being invoked.

A lot of LINQ is built this ways, though you may want to take a look at expressions.

苏璃陌 2024-12-31 02:28:16

您描述的 API 类型称为 Fluent API。请参阅前面的文章以获得很好的教程。

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

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

此致,

The type of API you are describing is called a Fluent API. Take a look at the preceeding article for a good tutorial.

With regard to delegate chaining, take a look at the LINQ extension methods in .NET 3.5, in particular how lambda functions (delegates) passed to a function result in an IEnumerable result which can then be chained with another extension method + lambda.

In your specific case you might need to create a class called a Functor to accept a delegate and return another Functor which too can be operated on by delegates.

Best regards,

可爱暴击 2024-12-31 02:28:16

使用 GetIncationList 你可以实现这一点。

 Delegate[] chain = chained.GetInvocationList();

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

using GetInvocationlist you can achieve this.

 Delegate[] chain = chained.GetInvocationList();

        int res = 10;
        for( int i = 0; i < chain.Length; i++ ) 
          {
              //Call chain[i]
                res =  chain[i](res);
          }
半衾梦 2024-12-31 02:28:16

我自己一直在研究一个类似的问题,其中涉及调用一系列委托并将一个委托的输出传递给下一个委托(依此类推......),所以我想您可能有兴趣查看我开发的代码作为概念验证:

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;
    }
}

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

I have been working on a similar problem myself which involved invoking a sequence of delegates and passing the output of one delegate to the next (and so on...) so thought you might be interested to see the code I developed as a proof-of-concept:

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;
    }
}

The sequence has to contain delegates of the same type so is not as powerful as the already accepted answer but with a few tweaks, both bits of code could be combined to provide a powerful solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文