How to initialize an array of custom objects

后端 未结 9 2474
粉色の甜心
粉色の甜心 2020-12-13 23:44

First, as this leads to my question, I\'ll start by noting that I\'ve worked with XML a fair bit in PowerShell, and like how I can read data from XML files, quickly, into ar

9条回答
  •  太阳男子
    2020-12-14 00:20

    I'd do something along these lines:

    $myitems =
    @([pscustomobject]@{name="Joe";age=32;info="something about him"},
    [pscustomobject]@{name="Sue";age=29;info="something about her"},
    [pscustomobject]@{name="Cat";age=12;info="something else"})
    

    Note that this only works in PowerShell 3, but since you did not mention the version in your question I'm assuming this does not matter for you.

    Update

    It has been mentioned in comments that if you do the following:

    $younger = $myitems | Where-Object { $_.age -lt 20 } 
    Write-Host "people younger than 20: $($younger.Length)" 
    

    You won't get 1 as you might expect. This happens when a single pscustomobject is returned. Now this is not a problem for most of other objects in PowerShell, because they have surrogate properties for Length and Count. Unfortunately pscustomobject does not. This is fixed in PowerShell 6.1.0. You can work around this by using operator @():

    $younger = @($myitems | Where-Object { $_.age -lt 20 })
    

    For more background see here and here.

    Update 2

    In PowerShell 5 one can use Classes to acheive similar functionality. For example you can define a class like this:

    class Person {
        [string]$name
        [int]$age
        [string]$info; `
    `
        Person(
        [string]$name,
        [int]$age,
        [string]$info
        ){
            $this.name = $name
            $this.age = $age
            $this.info = $info
        }
    }
    

    Backticks here are so that you could copy and paste it to the command line, they are not required in a script. Once the class is defined you can the create an array the usual way:

    $myitems =@([Person]::new("Joe",32,"something about him"),
    [Person]::new("Sue",29,"something about her"),
    [Person]::new("Cat",12,"something else"))
    

    Note that this way does not have the drawback mentioned in the previous update, even in PowerShell 5.

    Update 3

    You can also intialize a class object with a hashtable, similar to the first example. For that you need to make sure that a default contructor defined. If you do not provide any constructors, one will be created for you, but if you provide a non-default one, default constructor won't be there and you will need to define it explicitly. Here is an example with default constructor that is auto-created:

    class Person {
        [string]$name
        [int]$age
        [string]$info;
    }
    

    With that you can:

    $person = @([Person]@{name='Kevin';age=36;info="something about him"}
    [Person]@{name='Sue';age=29;info="something about her"}
    [Person]@{name='Cat';age=12;info="something else"})
    

    This is a bit more verbose, but also a bit more explicit. Thanks to @js2010 for pointing this out.

提交回复
热议问题