How to add hashtable to multidimensional array? Cannot assign values via member enumeration

后端 未结 1 690
傲寒
傲寒 2020-12-11 11:55

I\'m having trouble with adding hashtables to a multidimensional array. I coded the following:

$Data = @{BIBs = @(
           


        
1条回答
  •  囚心锁ツ
    2020-12-11 12:11

    tl;dr

    Setting a key / property value via member enumeration is not supported (see below).

    Instead, you must obtain the specific object whose .Bücher property you want to modify explicitly:

    ($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch'; Autor='Johann Doe' }
    

    Note: This assumes that:

    • only one element of array $Data.BIBs.BIB1 has a .Bücher property (key)
    • that, if the property / key does exist, it is nonempty and therefore is "truthy" in a Boolean context, such as the expression passed to ? (Where-Object); like member enumeration, this simplified Where-Object syntax - ? Bücher instead of ? { $_.Bücher } - is a PSv3+ feature called comparison statement.

    Mathias R. Jessen has provided the crucial pointer in comments on the question:

    PowerShell has an intentional asymmetry with respect to dot notation across collection-valued properties for getting values vs. setting values.

    • On getting, PSv3+ applies member enumeration, which, in a nutshell, allows you to access a property on a collection and implicitly get that property's value from each element IN that collection, with the results getting collected in an array.

    • On setting, member enumeration is not applied; the rationale is that the risk of unintentional modification of data is too high - see GitHub issue #5271 and in particular this comment by a core member of the PS team.

    The unfortunate aspect is that the current error message doesn't tell you that.
    It stems from the fact that when attempting to set a property at the collection level, the property is looked for only directly on the collection (instead of on its elements), where it (usually) doesn't exist.

    Let's take a look at a simplified example:

    $data = @{ # a hashtable
      a = ( # array of hashtables
        @{ b1 = 'b1' },
        @{ b2 = 'b2' },
        @{ b3 = 
          @{ b31 = 'b31' }, @{ b32 = 'b32' } # array of hashtables
        }
      )
    }
    

    On getting, everything works fine:

    PS> $data.a.b3
    
    Name                           Value                                                                                                                                                                                                                            
    ----                           -----                                                                                                                                                                                                                            
    b31                            b31                                                                                                                                                                                                                              
    b32                            b32                                                                                                                                                                                                                              
    

    Even though $data.a is an [object[]] array, an object (hashtable) with property .b3 was found among its elements, and that object's .b3 value is output.
    This is member enumeration in action (although the more typical uses is case for the property to exist on all elements of the array and for the individual values to be collected in an [object[]] array).

    On setting, PowerShell forgoes member enumeration and therefore unsuccessfully looks for a .b3 property only directly on the [object[]] instance that is $data.a and, of course, arrays have no .b3 property:

    PS> $data.a.b3 += @{ b33 = 'b33' }  # Try to add an element; !! FAILS
    
    The property 'b3' cannot be found on this object. 
    Verify that the property exists and can be set.
    ...
    

    0 讨论(0)
提交回复
热议问题