4

让我们以经典的一阶函数为例:

function Get-MyName { "George" }

function Say-Hi([scriptblock]$to) {
  Write-Host ("Hi "+(& $to))
}

这工作得很好:

Say-Hi { "Fred Flintstone" }

这不会:

Say-Hi Get-MyName

因为 Get-MyName 被评估,而不是作为值本身传递。如何将 Get-MyName 作为值传递?

4

4 回答 4

9

您必须将 Get-Myname 作为脚本块传递,因为这就是您定义变量类型的方式。

Say-Hi ${function:Get-MyName}
于 2013-04-12T17:45:30.880 回答
3

如果您准备牺牲[scriptblock]参数类型声明,那么还有另一种方法,可以说是最简单且有效的方法。只需[scriptblock]从参数中删除(或将其替换为[object]):

function Get-MyName { "George" }

function Say-Hi($to) {
  Write-Host ("Hi "+(& $to))
}

Say-Hi Get-MyName
Say-Hi { "George" }

所以 now$to可以是脚本块或命令名称(不仅仅是函数,还可以是别名、cmdlet 和脚本)。

唯一的缺点是声明Say-Hi不是那么自我描述。当然,如果您不拥有代码并且无法更改它,那么这根本不适用。

我希望 PowerShell 对此有特殊类型,请参阅此建议。在那种情况下function Say-Hi([command]$to)将是理想的。

于 2014-06-21T05:09:51.247 回答
2

这可能是一个更好的例子来说明问题和执行范围的细节。@mjolinor 的答案似乎很适合这个用例:

function Get-MyName($name) { $name; throw "Meh" }

function Say-Hi([scriptblock]$to) {
  try {
      Write-Host ("Hi "+(& $to $args)) # pass all other args to scriptblock
  } catch {
      Write-Host "Well hello, $_ exception!"
  }
}

命令及其输出:

PS C:\> Say-Hi ${function:Get-MyName} 'George'
Well hello, Meh exception

特别是,我使用这种模式来包装与不稳定的远程 SQL Server 数据库连接一起工作的函数,该连接休眠,然后重试几次,最终成功或引发更高的异常。

于 2016-10-27T20:02:13.263 回答
1

严格根据您的代码,正确答案是:

Say-Hi {(Get-MyName)}

这将产生“嗨乔治”

于 2014-06-20T19:11:17.467 回答