2

我有以下内容,但看起来很笨重:

if($config.contentDir){ 
    $contentDir = $config.contentDir
} else { 
    $contentDir = "contents"
}

有没有更好的方法来做到这一点?我在这里看到了这个答案,但它并不完全“更好”。只是想知道 6.0 是否带来了任何改进?

我可能要处理大量的配置选项,所以它会变得相当混乱。

4

4 回答 4

3

更新


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'

于 2019-09-24T03:34:45.710 回答
3

这个有点短。。。

$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"
于 2019-09-23T21:12:58.327 回答
2

如图Bill_Stewart所示,在 ps7 中有一个三元运算符。但是,您可以通过使用包含两项的数组并利用 PoSh 强制值的方式来获得类似的东西——$False0$True1

$Config = [PSCustomObject]@{
    ContentDir = 'SomewhereElse'
    }
#$Config.ContentDir = ''

$ContentDir = @('contents', $Config.ContentDir)[[bool]$Config.ContentDir]

$ContentDir     

注释掉第 4 行的SomewhereElse
输出 = 启用第 4 行的输出 =contents

于 2019-09-23T21:26:03.687 回答
0

有点像'||' 在重击中。如果第一个是 false 或 null,它将执行第二个。

[void](($contentDir = $config.contentDir) -or ($contentDir = "contents"))
于 2019-09-23T23:32:30.067 回答