在 C# 中传递的参数 "by name"

Arguments passed "by name" in C#

Scala 编程语言有一个巧妙的功能,称为 按名称参数传递,它允许某些参数仅在需要时进行评估.

例如,可以使用 curried 方法编写 while 循环,如下所示:

// This is Scala code. A simulated while loop
@scala.annotation.tailrec
def myWhile(condition: => Boolean)(actions: => Unit): Unit = {
  if(condition) {
    actions
    myWhile(condition)(actions)
  }
}

由于 Scala 的语法糖、闭包和——这里特别有趣——传递的能力,此方法可以像常规 while 循环一样使用表达式作为函数参数,在引用时进行计算(如 : => type 参数声明所示)。

例如,下面打印“Hello!”到控制台十次:

var i = 0
myWhile(i < 10) {
  println("Hello!")
  i += 1
}

对于那些需要了解发生了什么的人,每次 condition 出现在方法内的 if(...) 语句中时,都会对表达式 i < 10 求值,类似地, println("Hello!"); i += 1 会在每次 actions 出现在方法主体中时进行计算。当为下一次迭代递归调用 myWhile 时,表达式按原样传递,因为该方法需要表达式,而不是值。 Scala 术语这些通过名称 参数传递。

如果这些参数是按值传递的,那么 i < 10 将作为 false 传递给 myWhile,而“Hello!”将只打印一次,i 将递增一次,循环将无限执行。

(Scala 主要是一种 函数式 语言,这段代码甚至不接近 FP, 但这是一个简单的例子。)

我的问题是,有没有办法以这种方式将参数传递给 C# 函数?另请注意,我仅限于使用 C# 7.3。 :-(

听起来你可以和 Func`1 and Action 有点接近:

void MyWhile(Func<bool> condition, Action action) {
  while (condition()) {
    action();
  }
}

并调用为:

int i = 0;
MyWhile(() => i < 10, () => {
  Console.WriteLine("Hello!");
  ++i;
});

语法有点不同,但思路相似。