我有以下内容,但看起来很笨重:
if($config.contentDir){
$contentDir = $config.contentDir
} else {
$contentDir = "contents"
}
有没有更好的方法来做到这一点?我在这里看到了这个答案,但它并不完全“更好”。只是想知道 6.0 是否带来了任何改进?
我可能要处理大量的配置选项,所以它会变得相当混乱。
我有以下内容,但看起来很笨重:
if($config.contentDir){
$contentDir = $config.contentDir
} else {
$contentDir = "contents"
}
有没有更好的方法来做到这一点?我在这里看到了这个答案,但它并不完全“更好”。只是想知道 6.0 是否带来了任何改进?
我可能要处理大量的配置选项,所以它会变得相当混乱。
更新:
PowerShell (Core) 7.0中引入了Null-coalescing 运算符(以及三元运算符),它支持以下v7+ 解决方案:
$contentDir = $config.contentDir ?? 'content'
PowerShell v6- 解决方案:
您正在寻找的是null-coalescing,PowerShell 在 v7.0.0-preview.4 中没有。
现在,这将不得不做:
$contentDir = if ($null -eq $config.contentDir) { 'content' } else { $config.contentDir }
注意:$null
故意放在 LHS 上-eq
以明确测试,因为作为 RHS,如果要测试的值恰好是array$null
值,它将充当过滤器。
对Lee Daily 基于数组的答案的改编可以提供更简洁的解决方案:
$contentDir = ($config.ContentDir, 'content')[$null -eq $config.ContentDir]
使用将在 v7.0 中实现的三元运算符 (conditional)可以实现类似的简洁等效:
$contentDir = $null -eq $config.contentDir ? 'content' : $config.contentDir
但是,所有这些方法都有以下不良方面:
它们需要明确引用$null
; 请注意if ($config.ContentDir)
- 即将值强制为布尔值 - 可能适用于strings,但通常不稳健,因为非$null
值如也0
可以评估$false
。
$config.contentDir
,要测试的值$null
,必须访问两次,这可能会产生副作用。
定义一个名为的自定义函数??
可以解决这些问题:
# Custom function that emulates null-coalescing.
function ?? ($PossiblyNull, $ValueIfNull) {
if ($null -eq $PossiblyNull) { $ValueIfNull } else { $PossiblyNull }
}
$contentDir = ?? $config.contentDir 'content'
但是,这样的自定义函数有缺点:
自定义函数的缺点是:
您需要在要使用它们的每段代码中包含或导入它们。
如果您选择熟悉的名称,例如??
,操作数的放置可能会让人感到困惑,因为您必须(总是)在 PowerShell 中以不同的方式放置它们,给定作为函数的实现(例如,a ?? b
在 C# 中与?? $a $b
在 PowerShell 中) - 特别是一旦为真空 -合并在 PowerShell 中实现:请参阅下一节。
当然,调用函数会增加开销。
如果实现了这个 GitHub 功能请求,您将能够使用真正的 null-coalescing,这既是最简洁的解决方案,又避免了上述不良方面:
# Hopefully soon
$contentDir = $config.contentDir ?? 'content'
链接的 GitHub 问题中还提出了一个相关功能是空条件赋值,$config.ContentDir ?= 'content'
这个有点短。。。
$contentDir = if ( $config.contentDir ) { $config.contentDir } else { "contents" }
您还可以定义一个iif
函数:
function iif {
param(
[ScriptBlock] $testExpr,
[ScriptBlock] $trueExpr,
[ScriptBlock] $falseExpr
)
if ( & $testExpr ) {
& $trueExpr
}
else {
& $falseExpr
}
}
然后你可以缩短到这个:
$contentDir = iif { $config.contentDir } { $config.contentDir } { "contents" }
顺便说一句,看起来 PowerShell 的下一个版本将支持三元运算符(请参阅https://devblogs.microsoft.com/powershell/powershell-7-preview-4/),所以在未来,您将能够写出类似的东西:
$contentDir = $config.contentDir ? $config.contentDir : "contents"
如图Bill_Stewart
所示,在 ps7 中有一个三元运算符。但是,您可以通过使用包含两项的数组并利用 PoSh 强制值的方式来获得类似的东西——$False
给0
、$True
给1
。
$Config = [PSCustomObject]@{
ContentDir = 'SomewhereElse'
}
#$Config.ContentDir = ''
$ContentDir = @('contents', $Config.ContentDir)[[bool]$Config.ContentDir]
$ContentDir
注释掉第 4 行的SomewhereElse
输出 = 启用第 4 行的输出 =contents
有点像'||' 在重击中。如果第一个是 false 或 null,它将执行第二个。
[void](($contentDir = $config.contentDir) -or ($contentDir = "contents"))