Powershell - What does if($variable) test for?

前端 未结 2 1539
一向
一向 2021-01-19 15:42

In Powershell, what does if($variable) test for? Is this testing if the variable is set, is null, is true, or something else?

2条回答
  •  有刺的猬
    2021-01-19 16:32

    Powershell uses loose typing, and as a part of this any value can be used as a conditional expression. The logic of evaluating values to true or false (such values are often called "truthy" and "falsey") is in the System.Management.Automation.LanguagePrimitives.IsTrue function. The logic is the following:

    • $null evaluates to false.
    • $true and $false have their usual meaning.
    • A numeric value (int, double, decimal etc.) is truthy, if it is non-zero.
    • A string is truthy, if it is non-empty.
    • A switch parameter evaluates to true, if it has been supplied by the caller.
    function Test 
    {
       param ( [switch]$Option )
    }
    
    Test # $Option evaluates to false
    Test -Option # $Option evaluates to true
    
    # (Technically, $Option is not bool; it is of type SwitchParameter which, 
    # for almost all intents and purposes, can be used interchangeably with bool.)
    
    • A collection (implementing IList) uses the following logic: An empty collection is falsey; a collection with only one element evaluates to the truth value of its member; a collection with two or more elements is truthy.
    • Anything else is truthy.

    There are a couple of gotchas:

    • The char type is not a numeric type. Indeed, [System.Management.Automation.LanguagePrimitives]::IsTrue([char]0) returns True (per the final clause); yet if([char]0) { "Truthy" } else { "Falsey" } returns "Falsey". I wasn't able to find the reason why this happens.
    • As mentioned above, a collection with exactly one element is evaluated by evaluating its member. So what happens if you try to evaluate a collection which only contains itself (or a recursive or very deeply nested chain of collections, each with one element)? For science, you can test it:
    $array = New-Object -TypeName System.Object[] 1 # $array = new object[1]
    $array[0] = $array
    if($array) { "Truthy" } else { "Falsey" }
    

    (The answer is: it crashes the process with StackOverflowException.)

提交回复
热议问题