在 C# 中正确的柯里化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/411572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:20:47  来源:igfitidea点击:

Proper Currying in C#

c#lambdacurrying

提问by Rauhotz

Given a method DoSomethingthat takes a (parameterless) function and handles it in some way. Is there a better way to create the "overloads" for functions with parameters than the snippet below?

给定一个DoSomething采用(无参数)函数并以某种方式处理它的方法。有没有比下面的代码片段更好的方法来为带参数的函数创建“重载”?

public static TResult DoSomething<TResult>(Func<TResult> func)
{
    //call func() and do something else
}

public static TResult DoSomething<T0, TResult>(
    Func<T0, TResult> func,
    T0 arg0)
{
    return DoSomething(() => func(arg0));
}

public static TResult DoSomething<T0, T1, TResult>(
    Func<T0, T1, TResult> func,
    T0 arg0, T1 arg1)
{
    return DoSomething(arg => func(arg, arg1), arg0);
}

public static TResult DoSomething<T0, T1, T2, TResult>(
    Func<T0, T1, T2, TResult> func,
    T0 arg0, T1 arg1, T2 arg2)
{
    return DoSomething(arg => func(arg, arg1, arg2), arg0);
}

采纳答案by Jon Skeet

EDIT: As noted in comments, this is partial application rather than currying. I wrote a blog post on my understanding of the difference, which folks may find interesting.

编辑:如评论中所述,这是部分应用而不是柯里化。我写了一篇关于我对差异的理解的博客文章,人们可能会觉得有趣。

Well, it's not particularly different - but I'd separate out the currying part from the "calling DoSomething" part:

好吧,它并没有特别不同 - 但我会将柯里化部分与“调用 DoSomething”部分分开:

public static Func<TResult> Apply<TResult, TArg> (Func<TArg, TResult> func, TArg arg)
{
    return () => func(arg);
}

public static Func<TResult> Apply<TResult, TArg1, TArg2> (Func<TArg1, TArg2, TResult> func,
                                                          TArg1 arg1, TArg2 arg2)
{
    return () => func(arg1, arg2);
}

// etc

Then:

然后:

DoSomething(Apply(foo, 1));

That way you can reuse the currying code in other situations - including cases where you don't want to call the newly-returned delegate immediately. (You might want to curry it more later on, for example.)

这样您就可以在其他情况下重用柯里化代码 - 包括您不想立即调用新返回的委托的情况。(例如,您可能想稍后再对其进行咖喱处理。)

回答by leandromoh

The @Jon Skeet answer is right, but write by hand all possibles overload is something insane, so you can use a lib like Curryfythat do this job for you. Curryfy lib particularly exposes Curry, UnCurry and ApplyPartial extension methods, with a lot of overloads.

@Jon Skeet 的答案是正确的,但是手工编写所有可能的过载是一件很疯狂的事情,因此您可以使用像Curryfy这样的来为您完成这项工作。Curryfy 库特别公开了 Curry、UnCurry 和 ApplyPartial 扩展方法,有很多重载。