我们来看一下经典的一阶函数示例:
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作为值传递?
答案 0 :(得分:6)
您必须将Get-Myname作为脚本块传递,因为这就是您定义变量类型的方式。
Say-Hi ${function:Get-MyName}
答案 1 :(得分:2)
如果您准备牺牲[scriptblock]
参数类型声明
那么还有一种方法,可以说是最简单的使用和有效的方法。只是
从参数中删除[scriptblock]
(或将其替换为[object]
):
function Get-MyName { "George" }
function Say-Hi($to) {
Write-Host ("Hi "+(& $to))
}
Say-Hi Get-MyName
Say-Hi { "George" }
所以现在$to
可以是脚本块或命令名(不仅仅是一个函数,还有别名,cmdlet和脚本)。
唯一的缺点是Say-Hi
的声明不是那么自我描述。
当然,如果您不拥有代码而无法更改代码,那么这就是
根本不适用。
我希望PowerShell有一个特殊类型,请参阅此suggestion。
在这种情况下,function Say-Hi([command]$to)
将是理想的。
答案 2 :(得分: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数据库连接一起工作的函数,这些函数会休眠,然后在最终成功或抛出更高异常之前重试几次。
答案 3 :(得分:1)
严格根据您的代码,正确的答案是:
Say-Hi {(Get-MyName)}
这将产生“嗨乔治”