Powershell: Inconsistent behavior of $null assignment for property in custom class and variable with String type

Created on 18 Nov 2020  路  2Comments  路  Source: PowerShell/PowerShell

Steps to reproduce

Define a custom class and create a object of its type:

class ConstructionMaterial {
    [string]$Color
    [string]$Shape  
}
$obj = New-Object -TypeName ConstructionMaterial
$obj.Color = "Dummy"

Set Color property to $null and check the equality with eq operator:

PS /mnt/d/Lab/afd> $obj.Color.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS /mnt/d/Lab/afd> $obj.Color = $null
PS /mnt/d/Lab/afd> $obj.Color -eq $null
False

It outputted "False" and the behavior is not aligned with assigning $null to variable with the same "String" type:

PS /mnt/d/Lab/afd> $dummyObj = "Dummy"
PS /mnt/d/Lab/afd> $dummyObj.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS /mnt/d/Lab/afd> $dummyObj = $null
PS /mnt/d/Lab/afd> $dummyObj -eq $null
True

Expected behavior

$obj.Color -eq $null

Should return "True"

Actual behavior

"False" is returned

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.3
PSEdition                      Core
GitCommitId                    7.0.3
OS                             Linux 4.19.128-microsoft-standard #1 SMP Tue Jun 23 12:58:10 UTC 2020
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
Issue-Question Resolution-Answered

Most helpful comment

By design, [string]-typed variables and properties in PowerShell never contain $null - only the _empty string_, even if you explicitly assign $null.

In cases where a true null must be passed to a .NET method call, use [NullString]::Value.

While you can use this to effectively initialize [string] variables / properties to $null, it is best avoided, because other code may not expect to encounter true $null in [string] type-constrained values.

# !! $null is quietly converted to the empty string.
PS> [string] $foo = $null; $null -eq $foo; '' -eq $foo
False
True

# Works, but isn't obvious, and other code may not expect it.
PS> [string] $foo = [NullString]::Value; $null -eq $foo
True

By contrast, a variable or property that is _not_ type-constrained to [string] _is_ capable of storing true $null (and a reference to a non-existent variable also evaluates to $null).

PS> $bar = $null;  $null -eq $bar
True

All 2 comments

By design, [string]-typed variables and properties in PowerShell never contain $null - only the _empty string_, even if you explicitly assign $null.

In cases where a true null must be passed to a .NET method call, use [NullString]::Value.

While you can use this to effectively initialize [string] variables / properties to $null, it is best avoided, because other code may not expect to encounter true $null in [string] type-constrained values.

# !! $null is quietly converted to the empty string.
PS> [string] $foo = $null; $null -eq $foo; '' -eq $foo
False
True

# Works, but isn't obvious, and other code may not expect it.
PS> [string] $foo = [NullString]::Value; $null -eq $foo
True

By contrast, a variable or property that is _not_ type-constrained to [string] _is_ capable of storing true $null (and a reference to a non-existent variable also evaluates to $null).

PS> $bar = $null;  $null -eq $bar
True

@mklement0 , thanks a lot for the detailed explanation.

Was this page helpful?
0 / 5 - 0 ratings