Creating Objects in Windows PowerShell

Applies to: PowerShell 5.0.10240

I was recently in the beautiful city of Copenhagen, Denmark, where I was the guest of PSUG.DK, PowerShell User Group in Denmark. We met in the swanky Microsoft offices for a hands-on about classes in Windows PowerShell 5.0.

image

Microsoft Offices, Copenhagen, Denmark.

In the hands-on lab, we create a class, create instances of the class, and add constructors, properties and methods. Then, we try some of the more advanced features, like static properties and methods, inheritance, and interfaces.

To keep the class in a reasonably brief, when we create objects, I show New-Object and the New static method of objects, but gloss over creating objects from hash tables. In this blog post, I’d like to introduce all three methods and explain how to use them.

Creating Objects at the Command Line

There are (at least) three ways to create an object in Windows PowerShell. The first two techniques depend on the constructors defined in the class. The third one, hash tables, requires only a default constructor, that is, a constructor that has no parameters and takes no arguments or values.

For more information about creating objects in Windows PowerShell, see about_Object_Creation.

About constructors

Constructors are special methods that initialize the objects in a class. The constructors of a class determine which property values you need to specify in order to create a class.

One type of constructor is particularly important. It’s called a default constructor, although it’s often known as a null constructor or parameter-less constructor. A default constructor has no parameters and takes no arguments or values. It’s defined like this:

<className> ( ) { }

I’ll create a Tree class with Species, Height, and Deciduous properties. The Tree class has a default constructor (one with no parameters), a constructor that takes a Species string and a Height integer, and a Grow method.

class Tree {
 
    [String]$Species
    [int32]$Height
    [Boolean]Deciduous = $True
 
    Tree () {}
    Tree ([String]$Species, [int32]$Height)
    {
        $this.Species = $Species
        $this.Height = $Height
    }
 
    [int32] Grow ([int32]$Amount)
    {
        $this.Height += $Amount
        return $this.Height
    }
}

To find the constructors of any class, use the New static property of all classes. For example, to find the constructors of the Tree class, type:

PS C:\> [Tree]::New

OverloadDefinitions
-------------------
Tree new()
Tree new(string Species, int Height)

The result shows that you can create a Tree object with no parameters or with a string and an integer (in that order).

A constructor is a method, so when you use it, you do not specify parameter names and you must specify the values in the order that they are defined in the constructor. If you don’t, the command fails.

Constructors are special in two ways:

  • They have the same name as the class.
  • You don’t call them directly. Instead, you use a technique that takes a constructor, like the New-Object cmdlet or the New static method.

For more information about constructors, see about_Classes and Why Do We Need Constructors?

Use the New-Object cmdlet

To create an instance of a class with the New-Object cmdlet, use the following syntax:

New-Object -Typename <ClassName> -ArgumentList <Constructor>

To use a constructor, enter the values that the constructor specifies in a comma-separated list. Do not include any parameter names.

For example, to create a Tree with the following constructor, you need to enter one string and one integer.

Tree new(string Species, int Height)

Example:

PS C:\> $myTree = New-Object -TypeName Tree -ArgumentList 'Maple', 10
PS C:\> $myTree

Species Height Deciduous
------- ------ ---------
Maple   10     True

If you enter a different number of values, or values of a type that cannot be converted to the specified type, the command fails.

PS C:\> New-Object -TypeName Tree -ArgumentList 10, 'Maple'

New-Object : Cannot convert argument "1", with value: "Maple", for "Tree" to type "System.Int32": "Cannot convert value "Maple
"Input string was not in a correct format.""
At line:1 char:1
+ New-Object -TypeName Tree -ArgumentList 10, 'Maple'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

The Tree class also has a default constructor — one with no parameters. To create a Tree object with the default constructor, just omit the ArgumentList parameter. Then, you can assign values to the properties individually.

PS C:\> $myTree = New-Object -TypeName Tree
PS C:\> $myTree

Species Height Deciduous
------- ------ ---------
0 True

PS C:\> $myTree.Species = 'Maple'
PS C:\> $myTree.Height = 10
PS C:\> $myTree.Deciduous = $True

Use the New static method

You can also use the New method to create an object. (The method isn’t new. That’s its name.) The New method is a static method — a method of a class, not a method of an object — so you use the syntax with two consecutive colons (::) to call it.

The New method typically requires less typing than New-Object, but it’s a bit less familiar to PowerShell users.

To use the new method to create an object, use the following syntax:

[<ClassName>]::New(<Constructor>)

Again, when using a constructor, enter the values that the constructor specifies in a comma-separated list. Be careful to enter the values in the order that the constructor specifies. Do not include any parameter names.

For example, to create a Tree object with the following constructor:

Tree new(string Species, int Height)

Type:

[Tree]::New('Maple', 10)

To use the default constructor, leave the parentheses empty. They’re still required to distinguish the New method, which creates a new object, from the New property, which stores the constructors.

[Tree]::New()

Use a Hash Table

A hash table is a very convenient way to create an object. Although it typically requires more typing than using New-Object or the New static method, you don’t have to use a particular constructor.

Because you specify parameter names, you can specify the values in any order. (The keys in a hash table are unordered by definition, so the order cannot matter.)

However, this method works only when the class has a default constructor, that is, a constructor with no parameters. And, the properties that you specify in the hash table must be “settable,” that is, they cannot be read-only.

For example, the Tree class has a default constructor.

PS C:> [Tree]::New

OverloadDefinitions
-------------------
Tree new()     # <------------------------ This is the default constructor
Tree new(string Species, int Height)

To create an object with a hash table, use the following syntax:

[ClassName]@{<Parameter>=<Value>; <Parameter>=<Value>...}

For example:

[Tree]@{Species='Maple'; Height=10}

However, you can also create a hash table that does not match a constructor. And, because you specify the parameter names, the order of the values does not matter.

These commands work, too. The property values that you don't specify are left undefined.

[Tree]@{Height=10; Species='Maple'}
[Tree]@{Deciduous=$True; Height=10; Species='Maple'}
[Tree]@{Species='Maple'}

Hash Tables and PowerShell Classes

Hash tables are so convenient that many argue that they should be the primary way of creating PowerShell classes.

They are also particularly well-suited to PowerShell classes, because Windows PowerShell adds a default constructor automatically to every class.

PS C:\> class AnyClass {}
PS C:\> [AnyClass]::New

OverloadDefinitions
-------------------
AnyClass new()

When you create your own constructor, the default constructor disappears and you have to recreate it.

Thus, several people have argued that you should not create constructors in a PowerShell class. You should just leave the default constructor and let uses create objects with hash tables.

I think this is a good general practice, but there might be cases where you want to require that every instance of a class has a particular property value. In that case, you need to omit the default constructor and create only constructors that include the required property value.

So, there you have it. You can create classes and instances of those classes. Thanks again to Claus, Heine, and all the fantastic PowerShell folks in Denmark.

June Blender is a technology evangelist at SAPIEN Technologies, Inc and a Windows PowerShell MVP. You can reach her at juneb@sapien.com and follow her on Twitter at @juneb_get_help.