Search code examples
powershellpsobject

psobject declaration literals - Is there a way for a property value to reference the value of another property within the declaration itself?


Simply put, is there a way to reference (existing) property values inside of a psobject declaration literal, basically like this?

[pscustomobject] @{
    Number = 5
    IsLessThanZero = $this.Number -lt 0
}




Response to comments and answers:

  • MUCH thanks to both Santiago and Michael for filling in the gaps with crucial details that address behavioral subtleties. They have been exceptionally helpful, dependable and accurate resources for so many of us.

  • The example provided in my question purposefully did not assign the psobject to a variable; the point was to illustrate how to access said properties during a common scenario: creating a psobject and outputting it at the same time. This could have been emphasized and clarified with:

    [pscustomobject] @{
        Number = 5
        IsLessThanZero = $this.Number -lt 0
    } | Out-Default
    
  • The answers by Santiago and Michael cover both static and dynamic approaches; it's really nice to have both illustrated here on the same page.

    • The question's simplified example doesn't necessarily demand a dynamic solution since:
      • The value for .Number isn't modified in the time between the psobject's creation and its output
      • There's only a single object with no code/logic before or after
  • The example uses $this simply to indicate the current object (the question isn't about classes, but the idea is essentially the same). Choosing $_ could be confusing as there's no implied pipe prior to the psobject declaration.

    • My comment about this being a possible duplicate of another question: That question's example does take advantage of $_ (which my example does not), so they are in fact different scenarios.

Solution

  • Santiago's helpful answer is focused on a dynamic solution that makes the .IsLessThanZero property dynamically reflect the then-current value of the .Number property.


    By contrast, you seem to be looking for a solution based on [pscustomobject] literals, i.e. to initialize the .IsLessThanZero property statically, based on the initial, literally specified .Number value earlier in the same (pseudo) hashtable (ostensibly) cast to [pscustomobject] (the [pscustomobject] @{ ... } construct is syntactic sugar for constructing [pscustomobject] instances).

    As of PowerShell 7.4.x, there is no syntactic sugar to support such intra-hashtable cross-references.

    For now, you can use the following workaround:

    [pscustomobject] @{
        Number = ($number = 5)
        IsLessThanZero = $number -lt 0
    }
    
    • That is, assignment $number = 5 is used to capture the property value in variable $number, in combination with (...) enclosure, which passes the assigned value through.

    • The $number variable can then be used in subsequent entries (property definitions), as shown.

    Note: The $number variable will linger in the caller's scope; to avoid that, you can enclose the entire expression in & { ... }, which outputs the constructed object while confining the variable assignments to a transient child scope.