PowerShell: Array of Class objects inside a Class

The below example should get you going for now!

You define an array of objects by simply putting [] after the type, so Volume[]

At the bottom of the snippet are 2 examples that show how to access the volumes data too.

Class Volume {
  [String]$ID
  [String]$Name 
}

Class Storage {
  [String]$Name
  [String]$IP
  [Volume[]]$Volumes 
}

# Create a volume object
$volume1 = New-Object Volume
$volume1.ID = '1'
$volume1.Name = 'Data'

# Create another volume object
$volume2 = New-Object Volume
$volume2.ID = '2'
$volume2.Name = 'Log'

# Create a storage object
$storage = New-Object Storage
$storage.Name = 'SomeStorage'
$storage.IP = '0.0.0.0'

# Add the volume objects
$storage.Volumes += $volume1
$storage.Volumes += $volume2

# access a volume by name or index
$storage.Volumes | Where-Object {$_.Name -eq 'Data'}
$storage.Volumes[0]

Educational N.B by zett42 and santiago squarzon

The array is inefficient when you add many elements one-by-one. You might want to have a look at ArrayList / List types.

You could instead use [List[Volume]]$Volumes = [List[Volume]]::new() in your Storage class. Make sure to put a using namespace System.Collections.Generic at the top of your script. Then when you add volumes do $storage.Volumes.Add($volume1)


I did some performance testing for this, i added 10_000 volumes to the object. The array took 9.3 seconds, and the list took 0.93 seconds, a 10 fold performance improvement.

Array - Quadratic - O(N²)

+= recreates the entire array, it copies the old contents into a new array along with the new element.

ArrayList - Constant - O(1)

ArrayList has O(n) time complexity for arbitrary indices of add/remove, but O(1) for the operation at the end of the list.

using namespace System.Collections.Generic

Class Volume {
  [String]$ID
  [String]$Name 
}

Class Storage {
  [String]$Name
  [String]$IP
  [List[Volume]]$Volumes = [List[Volume]]::new()
}

# Create volume objects
$volume1 = New-Object Volume
$volume1.ID = '1'
$volume1.Name = 'Data'

# Create another volume object
$volume2 = New-Object Volume
$volume2.ID = '2'
$volume2.Name = 'Log'

# Create a storage object
$storage = New-Object Storage
$storage.Name = 'SomeStorage'
$storage.IP = '0.0.0.0'

# Add the volume objects
$storage.Volumes.Add($volume1)
$storage.Volumes.Add($volume2)

# access a volume by name or index
$storage.Volumes | Where-Object {$_.Name -eq 'Data'}
$storage.Volumes[0]