为什么我要将Func/Func<T>作为参数包含?

3

我承认它们可以很有用,但我正在努力理解在什么情况下我实际上想要将一个函数作为方法的参数。

public void WeirdMethod(int myNumber, func op);

就设计和功能而言,有哪些情况下我需要考虑这个?“可重用性”的理论并没有帮助我多少。最好提供真实世界的场景。帮我像你一样思考,哈哈。
以下是我了解到的:
- 这将允许我传递一个委托。 - 这将允许我使用 lambda 表达式。
是的……
注: 我知道这个线程会被关闭,因为没有“正确”的答案。但我认为刚刚为我点击的是“延迟计算”。

3
这里提供的一些答案可能更有意义,如果您先阅读关于Map-Reduce /函数式编程的介绍性文章:http://www.joelonsoftware.com/items/2006/08/01.html - meklarian
5个回答

4
  • 将操作推迟到以后的时间。一个非常实际的例子是将更改跟踪推迟到对象树完全填充之后。每个类型或存储库都可以告诉您它想要做什么,调用者可以决定何时实际执行。

  • 逻辑组合(正如Justin Niessner所提到的)。

  • 抽象,例如(“这是一个具有输入和输出的合同,但只要它满足合同,我就不关心它的实现方式)。例如,您可以向一个方法传递一个“statusWriter”Func,该方法可能会写入控制台、调试窗口、日志文件、数据库或根本不做任何事情。所有使用方法知道的是它消耗了一种类型,并在需要时调用它。

  • 沿着同样的路线,将Func传递给方法允许通过抽象和简单的方式允许调用者定义where谓词。我经常使用这种范例来支持强类型过滤器应用于结果(不是LINQ to SQL,只是根据调用者的意愿过滤信息列表)。

  • 优雅的函数编程范式,例如这个例子展示了使用匿名函数进行递归的方法。如果没有将一个函数传递给另一个函数(特别是在缩写形式中),这些构造将变得冗长/不可能。


我完全忘记了将函数视为与其返回值在语义上等价的事实。 - Sinaesthetic

3
一个普遍的场景是当你必须将延迟计算传递给你的方法时。这在计算某些东西很昂贵时非常有用,例如在缓存某些内容时。
public Guid GetFromCache(string key, Func<Guid> make) {
    Guid res;
    if (!cache.TryGetValue(key, out res)) {
        res = make();
        cache.Add(key, res);
    }
    return res;
}

现在你可以按照以下方式调用此方法:
Guid guid = GetFromCache(myKey, () => database.MakeNewGuid());

感谢您包含Lambda。有时候,仅仅在概念解释之后看到它就足够了。 - Sinaesthetic

3
如果您有一些异步任务并且希望为其提供回调方法,该怎么办?

0

它们使您能够柯里化函数以及使用函数组合。


有点儿低分的投票者可否评论一下?在这两种情况下,传递和返回函数作为值给/自函数的能力是至关重要的。委托为您提供了C#中的该机制。 - Justin Niessner
2
我不是那个给你点踩的人,但我也没有点赞,因为我觉得那些不理解Func的人也可能不知道柯里化是什么或如何进行函数组合 - Scott Chamberlain
我和Scott一样,没有(也不会)给这个回答点踩,但我怀疑这个回答虽然正确,但对于这个问题的预期受众并没有太大的帮助。 - Adam Robinson

0

虽然你几乎肯定以前已经使用过委托(因为那就是事件的本质),但 LINQ 作为将委托作为函数参数传递有用的主要示例。

想一想 Where。您正在向使用它作为执行的一部分的函数提供一段逻辑(特别是满足您标准的定义——无论它们是什么)。


我不是在尝试识别使用函数的实例。我正在尝试理解它们的目的,以便我可以开始在我的实现代码中使用它们。 - Sinaesthetic
1
@Sinaesthetic:你明白为什么LINQ中要使用它们吗? - Adam Robinson
是的,我经常使用它们。 - Sinaesthetic
如果你明白它们为什么在那里使用,那么你在问什么?你说:“我正在试图弄清楚什么时候我会想要将一个函数作为方法的参数。” - Adam Robinson
我一直在琢磨什么时候我会想将函数作为方法的参数,而不是在哪里遇到一个作为参数的情况。我想了解在我自己的实现中何时使用它们。 - Sinaesthetic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接