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

  • Note, the 2 answers below offer what is known as computed properties in C#, meaning that the value of IsLessThanZero can change depending on the value of Number.

    If you don't expect the value of Number to change, then the answers on the following links might suffice:


    Use a ScriptProperty, either via Update-TypeData:

    $updateTypeDataSplat = @{
        TypeName   = 'myType'
        MemberName = 'IsLessThanZero'
        Value      = { $this.Number -lt 0 }
        MemberType = 'ScriptProperty'
    }
    
    Update-TypeData @updateTypeDataSplat
    
    $myObject = [pscustomobject] @{
        Number     = 5
        PSTypeName = 'myType'
    }
    $myObject
    

    Or by adding the ScriptProperty to the psobject itself:

    $myObject = [pscustomobject] @{
        Number = 5
    }
    $myObject.PSObject.Members.Add([psscriptproperty]::new(
            'IsLessThanZero', { $this.Number -lt 0 }))
    $myObject