【问题标题】:C# Passing Function as Argument [duplicate]C#将函数作为参数传递[重复]
【发布时间】:2011-04-07 00:50:24
【问题描述】:

我用 C# 编写了一个函数来进行数值微分。它看起来像这样:

public double Diff(double x)
{
    double h = 0.0000001;

    return (Function(x + h) - Function(x)) / h;
}

我希望能够传入任何函数,例如:

public double Diff(double x, function f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

我认为委托可以做到这一点(也许?),但我不确定如何使用它们。

任何帮助将不胜感激。

【问题讨论】:

标签: c# arguments


【解决方案1】:
public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

用法:

var ReturnValue = Runner(() => GetUser(99));

【讨论】:

  • 我很好奇,为什么是泛型类型参数?
  • 我收到此错误:无法从用法中推断出方法“Runner(Func)”的类型参数。尝试明确指定类型参数。
  • 你的“funcToRun”方法签名是什么?
【解决方案2】:

使用上面提到的 Func 是可行的,但也有代理执行相同的任务并在命名中定义意图:

public delegate double MyFunction(double x);

public double Diff(double x, MyFunction f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

public double MyFunctionMethod(double x)
{
    // Can add more complicated logic here
    return x + 10;
}

public void Client()
{
    double result = Diff(1.234, x => x * 456.1234);
    double secondResult = Diff(2.345, MyFunctionMethod);
}

【讨论】:

  • 在 3.5 及更高版本中,Funcs 和委托是可互换的,这意味着匿名委托和 lambda(它们是匿名委托的语法糖)也可以使用。因此,将参数指定为 Func 还是采用双精度并返回双精度的委托并不重要。命名委托给您的唯一真正优势是能够添加 xml-doc cmets;描述性名称与参数名称而不是类型一样易于实现。
  • 我认为方法原型仍然使代码比 Func 更具可读性 - 不仅仅是命名使代码可读,正如你所说,这并不能阻止你将 lambdas 传递到代码中。
  • 如果委托类型的命名对于代码的清晰度如此重要,我认为在大多数情况下我会倾向于接口和实现。
  • @qstarin 这不仅仅是委托的命名,而是方法必须采用的参数的命名,特别是如果它们只是本机类型。你是对的,我主要使用接口而不是委托
  • 如果我将其中一个作为提供通用功能的通用函数,(具有不那么常见的返回类型)一切正常,直到我尝试将它与 void 一起使用。我真的需要使用 Action 而不是 Func 来创建一个重复的函数还是有更好的方法?
【解决方案3】:

.Net(v2 及更高版本)中有几个泛型类型,它们使作为委托传递函数非常容易。

对于具有返回类型的函数,有 Func,对于没有返回类型的函数,有 Action。

Func 和 Action 都可以声明为采用 0 到 4 个参数。例如,Func 将一个 double 作为参数并返回一个 int。 Action 将三个 double 作为参数,不返回任何内容(void)。

所以你可以声明你的 Diff 函数来获取 Func:

public double Diff(double x, Func<double, double> f) {
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

然后你这样称呼它,只需给它一个适合你的 Func 或 Action 签名的函数名称:

double result = Diff(myValue, Function);

您甚至可以使用 lambda 语法编写函数:

double result = Diff(myValue, d => Math.Sqrt(d * 3.14));

【讨论】:

  • 在 .NET 4 中,FuncAction 都已更新为允许使用 up to 16 参数。
  • 返回一个Func&lt;double, double&gt; 是很酷的事情,它是输入函数的一阶导数,当然是数值计算的。 return x =&gt; (f(x + h) - f(x)) / h; 你甚至可以编写一个重载,返回输入函数的n th 导数。
猜你喜欢
  • 2013-08-13
  • 2022-01-16
  • 2017-02-12
  • 2023-03-03
  • 2019-07-23
  • 2017-01-08
  • 2014-10-27
  • 2016-01-21
相关资源
最近更新 更多