让我们以经典的一阶函数为例:
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 作为值传递?
让我们以经典的一阶函数为例:
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 作为值传递?
您必须将 Get-Myname 作为脚本块传递,因为这就是您定义变量类型的方式。
Say-Hi ${function:Get-MyName}
如果您准备牺牲[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)
将是理想的。
这可能是一个更好的例子来说明问题和执行范围的细节。@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 数据库连接一起工作的函数,该连接休眠,然后重试几次,最终成功或引发更高的异常。
严格根据您的代码,正确答案是:
Say-Hi {(Get-MyName)}
这将产生“嗨乔治”