Reputation: 43
I've started using PowerShell to get some things done and played with the variable $null
in PowerShell.
I've encountered the problem that when I assign the variable $null
to a variable defined in a class, the test returns false
not true
.
Example Code:
class test {
[string]$test1
}
$test = [test]::new()
$test.test1 = $null
$null -eq $test2 # tests true
$null -eq $test.test1 # tests false
Now the test of the undefinded variable $test2
returns true
as every undefined variable in PowerShell is assigned $null
.
But if I test the property test1
of the object test
which I assigned $null
tests false
for $null
Is it because in PowerShell $null
is an object with the value $null
and now the property of the object is not $null
as it has the object $null
assigned to it with an empty value?
I've read into the docs of Microsoft "Everything you wanted to know about $null", but it does not enlighten me.
If I do not initialize the variable, then it will test true
for $null
.
Upvotes: 4
Views: 1062
Reputation: 437111
To elaborate on robdy's helpful answer:
By design, [string]
-typed variables, parameter variables, and custom-class properties in PowerShell do not store $null
[1], only actual string values. Assigning $null
always converts to ''
(the empty string).
Below, $var
receives ''
, not $null
, due to being [string]
-typed; therefore, the first -eq
test fails and the second succeeds.
[string] $var = $null; $null -eq $var; '' -eq $var
Note that other .NET reference types (as opposed to value types, which fundamentally cannot be null) are not affected in PowerShell; that is, you can assign $null
to them. Notably, this also applies to [object]
. Note that not type-constraining a variable / parameter / property is the same as [object]
-typing it.
That an uninitialized [string]
property in a PowerShell class
nonetheless currently defaults to $null
should be considered a bug - see GitHub issue #7294.
The inconsistency becomes obvious if you explicitly initialize to $null
, which again converts to ''
and makes the test fail.
class test { [string]$test1=$null }; $null -eq [test]::new().test1
Should the bug be fixed and you truly need a $null
value in a [string]
-typed property - which is ill-advised in the context of PowerShell code - you'd have to use [NullString]::Value
, as shown in the answer linked to below:
class test { [string]$test1 = [NullString]::Value }; $null -eq [test]::new().test1
For more information, see this answer.
[1] The inability to store $null
is a limitation that PowerShell imposes, in the interest of simplification. The underlying .NET type, System.String
, typically does not have this limitation in other languages, notably not in C#.
Upvotes: 4
Reputation: 11254
If you're using a type contstraint
like [string]
or [int]
Powershell initializes members at null
-assignment with the default of the contrained type.
As @robdy states in above answer you've either check for the types default value or remove the constraint.
This may become more obvious if you're using a [int]
type contstraint:
class test {
[int]$i1 = 42
}
$test = [test]::new()
Write-Host $test.i1
$test.i1 = $null
Write-Host $test.i1
Output:
42
0
Upvotes: 3
Reputation: 5217
$test.test1
is not $null
, it's empty string (because you explicitely defined it's value to be [string]
):
C:\> $test.test1.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
Proof:
C:\> $test.test1 -eq ""
True
Upvotes: 4