C#传递函数作为参数

Ash*_*Ash 123 c# arguments

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

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

    return (Function(x + h) - Function(x)) / h;
}
Run Code Online (Sandbox Code Playgroud)

我希望能够传递任何功能,如:

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

    return (f(x + h) - f(x)) / h;
}
Run Code Online (Sandbox Code Playgroud)

我认为这对代表来说是可能的(也许?)但是我不确定如何使用它们.

任何帮助将不胜感激.

que*_*rin 160

.Net(v2及更高版本)中有几种泛型类型,它们使代理的传递函数非常容易.

对于具有返回类型的函数,有Func <>,对于没有返回类型的函数,有Action <>.

Func和Action都可以声明为0到4个参数.例如,Func <double,int>将一个double作为参数并返回一个int.Action <double,double,double>将三个双精度作为参数并且不返回任何内容(void).

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

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

    return (f(x + h) - f(x)) / h;
}
Run Code Online (Sandbox Code Playgroud)

然后你这样称呼它,简单地给它一个适合你的Func或Action签名的函数的名字:

double result = Diff(myValue, Function);
Run Code Online (Sandbox Code Playgroud)

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

double result = Diff(myValue, d => Math.Sqrt(d * 3.14));
Run Code Online (Sandbox Code Playgroud)

  • 在.NET 4中,"Func"和"Action"都已更新,允许[最多16个](http://msdn.microsoft.com/en-us/library/dd402862.aspx)参数. (26认同)
  • 一个非常酷的事情是返回一个`Func <double,double>`这是输入函数的一阶导数,当然是数值计算的.`return x =>(f(x + h) - f(x))/ h;`你甚至可以写一个返回输入函数的第n个导数的重载. (5认同)

Ian*_*son 132

使用上面提到的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);
}
Run Code Online (Sandbox Code Playgroud)

  • 在3.5及更高版本中,Func <>和委托是可互换的,这意味着也可以使用匿名委托和lambdas(匿名委托的语法糖).因此,将参数指定为Func <double,double>或者采用double并返回double的委托并不重要.命名委托给你的唯一真正优势是能够添加xml-doc注释; 描述性名称与参数名称一样容易实现,而不是类型. (5认同)
  • 我认为方法原型仍然使代码比Func <x,y>更具可读性 - 它不仅仅是使代码可读的命名,正如你所说的那样,并不能阻止你将lambda传递给代码. (3认同)

kra*_*s88 10

public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}
Run Code Online (Sandbox Code Playgroud)

用法:

var ReturnValue = Runner(() => GetUser(99));
Run Code Online (Sandbox Code Playgroud)

  • 我收到此错误:无法从用法推断方法'Runner &lt;T&gt;(Func &lt;T&gt;)'的类型参数。尝试显式指定类型参数。 (2认同)