返回委托的方法

本文关键字:方法 返回 | 更新日期: 2023-09-27 18:01:48

我正在努力理解委托和lambda表达式,并且正在阅读stackoverflow上的一些问题,并在这个评论中的第二个例子让我完全迷失的地方找到了这篇文章。让我感到困惑的第一件事是没有在任何地方定义list参数(我知道它是返回类型的输入参数,但我发现很难理解这段代码),但我认为,通过看到如何在实践中使用这样的定义,一切都会变得更加清楚(这是我很难掌握的第二件事)。

如何在实践中使用下列方法?

public Func<IList<T>, T> SelectionMethod<T>()
{
    return list => list.First();
}
public Func<float, float> QuadraticFunctionMaker(float a , float b , float c)
{
    return (x) => { return a * x * x  + b * x + c; };
}

返回委托的方法

参数是定义的,只是它们的类型是推断出来的。在您的示例中,参数定义分别是=> - list(推断为IList<T>类型)和x(推断为float类型)之前的部分。

第一个委托对应的签名为:

T SomeMethod<T>(IList<T> list)

第二个是:

float SomeMethod(float x)

由于编译器知道委托的签名必须是什么,它可以自动推断所需的类型。如果您要使用老派的显式语法编写委托,它将看起来像这样:

return (Func<IList<T>, T>)(delegate (IList<T> list) { return list.First(); });

如果真的想使用显式类型,可以根据需要指定类型:

(IList<T> list) => list.First()

当你真正想要调用委托时,你需要传递参数,例如:

SelectionMethod<string>()(new List<string>())

第一个lambda表达式非常简单。第二个额外关闭了"创建者"函数的参数,这意味着您可以访问委托主体中"创建者"的参数。这在纯不可变代码中是完全安全的,但如果你要处理可变引用类型和副作用,可能会很棘手——在你对这些做任何疯狂的事情之前,确保你正确地理解了语义。

根据你的函数式编程经验,认识到所有这些都只是编译器的诡计可能会有所帮助。这两个方法将编译成类似这样的内容:

public Func<IList<T>, T> SelectionMethod<T>()
{
  return new Func<IList<T>, T>(__HiddenAnonymousMethod);
}
private T __HiddenAnonymousMethod<T>(IList<T> list)
{
  return list.First();
}

由于闭包的关系,第二个例子更加复杂——我们需要创建一个"helper对象"来保存捕获的局部变量:

private class __HiddenAnonymousClass
{
  float a, b, c;
  public __HiddenAnonymousClass(float a, float b, float c)
  {
    this.a = a; this.b = b; this.c = c;
  }
  public float __HiddenAnonymousMethod(float x)
  {
    return a * x * x  + b * x + c;
  }
}
public Func<float, float> QuadraticFunctionMaker(float a , float b , float c)
{
  return new Func<float, float>
    (new __HiddenAnonymousClass(a, b, c).__HiddenAnonymousMethod);
}