Элегантный способ установки значения по умолчанию для переменной в Powershell 6.0? - PullRequest
2 голосов
/ 24 сентября 2019

У меня есть следующее, которое работает, но выглядит неуклюже:

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

Есть ли лучший способ сделать это?Я видел этот ответ здесь , но он не совсем "лучше".Просто интересно, принесло ли 6.0 какие-либо улучшения?

Я, вероятно, буду обрабатывать большое количество опций конфигурации, так что это будет довольно грязно.

Ответы [ 4 ]

3 голосов
/ 24 сентября 2019

Это немного короче ...

$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"
2 голосов
/ 24 сентября 2019

То, что вы ищете, это объединение нулей , которого нет в PowerShell по состоянию на v7.0.0-preview.4.

Покадля этого нужно сделать:

$contentDir = if ($null -eq $config.contentDir) { 'content' } else { $config.contentDir }

Примечание: $null специально помещен на LHS -eq, чтобы однозначно проверить на $null, потому что как RHS он будет действовать как фильтр , если проверяемое значение оказывается массивом -оценным.

Адаптация ответа Ли Дейли на основе массива включает более краткое решение:

$contentDir = ($config.ContentDir, 'content')[$null -eq $config.ContentDir]

Использование троичного оператора (условного) , который будет реализован в v7.0, включает аналогично краткий эквивалент:

$contentDir = $null -eq $config.contentDir ? 'content' : $config.contentDir

Однако все эти подходы имеют следующие нежелательные аспекты :

  • Они требуют явной ссылкидо $null;обратите внимание, что if ($config.ContentDir) - то есть приведение значения к логическому значению - может работать с строками , но, как правило, не является устойчивым, поскольку значения, отличные от $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) - especiсоюзник, когда в PowerShell реализовано истинное объединение нулей: см. следующий раздел.

  • И, конечно, вызов функции добавляет издержки.


Если реализован этот запрос функции GitHub , вы сможете использовать true null-coalescing , который одновременно является наиболее лаконичным решением и избегает вышеупомянутых нежелательных аспектов :

# Hopefully soon
$contentDir = $config.contentDir ?? 'content'

Связанная функция, также предложенная в связанном выпуске GitHub, - нулевое условное назначение , $config.ContentDir ?= 'content'

2 голосов
/ 24 сентября 2019

Как показало 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

0 голосов
/ 24 сентября 2019

Вроде как '||'в баш.Если первый является ложным или нулевым, он будет делать второй.

[void](($contentDir = $config.contentDir) -or ($contentDir = "contents"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...