5

C#和其他语言通常有空条件?.

A?.B?.Do($C);

当 A 或 B 为空时不会出错。如何在 powershell 中实现类似的功能,更好的方法是:

if ($A) {
  if ($B) {
    $A.B.Do($C);
  }
}
4

3 回答 3

8

Powershell 7 Preview 5 具有处理空值的运算符。https://devblogs.microsoft.com/powershell/powershell-7-preview-5/

$a = $null

$a ?? 'is null' # return $a or string if null
is null

$a ??= 'no longer null'  # assign if null

$a ?? 'is null'
no longer null

编辑:Powershell 7 Preview 6 增加了更多新的运算符: https ://devblogs.microsoft.com/powershell/powershell-7-preview-6/ 。因为变量名可以有一个“?” 在名称中,您必须用花括号将变量名称括起来:

${A}?.${B}?.Do($C)
于 2019-10-25T15:02:18.497 回答
4

正如Mathias R. Jessen 的回答所指出的,PowerShell默认情况下具有关于属性访问[1]的空条件访问行为(null-soaking);例如,$noSuchVar.Prop悄悄地返回$null

js2010 的答案显示了相关的空合并运算符 ( ??) /空条件赋值运算符 ( ??=),它们在 PowerShell [Core] v 7.1+ 中可用

但是,直到 PowerShell 7.0

  • 没有办法以空条件忽略方法调用$noSuchVar.Foo()总是失败。

  • 同样,没有办法以空条件忽略(数组)索引$noSuchVar[0]总是失败。

  • 如果您选择更严格的行为 with Set-StrictMode,则即使是属性访问 null-soaking 也不再是一种选择:withSet-StrictMode -Version 1或更高,$noSuchVar.Prop会导致错误。

PowerShell [Core] 7.1+中,可以使用空条件(空浸泡)运算符

新运营商:

  • 原则上与 C# 中形式相同?.?[...]

  • 但是 -从 v7.1 开始-需要将变量名包含在{...}

也就是说,您目前不能只使用$noSuchVar?.Foo(), $A?.B, or $A?[1], 您必须使用
${noSuchVar}?.Foo(), ${A}?.B, or${A}?[1]

这种繁琐语法的原因是存在向后兼容性问题,因为?它是变量名中的合法字符,因此假设现有代码(例如)$var? = @{ one = 1}; $var?.one可能会在不使用{...}消除变量名歧义的情况下中断;在实践中,这种使用极为罕见

如果您认为不妨碍新语法比可能破坏以变量名结尾的脚本更重要?,请在此 GitHub 问题上发表您的意见。


[1] PowerShell 的默认行为甚至提供了存在条件属性访问;例如,$someObject.NoSuchProp悄悄地返回$null

于 2019-10-27T03:47:40.627 回答
4

PowerShell 没有空条件运算符,但它会默默地忽略空值表达式上的属性引用,因此您可以“跳过”到链末尾的方法调用:

if($null -ne $A.B){
  $A.B.Do($C)
}

适用于任何深度:

if($null -ne ($target = $A.B.C.D.E)){
    $target.Do($C)
}
于 2019-10-25T14:52:06.380 回答