PowerShell

The curious case of $null should be on the left side of equality comparisons PSScriptAnalyzer

If you're using VSCode with Powershell extension, you probably got used to PSScriptAnalyzer giving you all kind of tips on optimizing things. It makes your code better. Chris Bergmeister does a great job working on it. One of the tips PSScriptAnalyzer gives you when you use $null on the right side of the comparison.

$Process = Get-Process
if ($Process -eq $null) {
    #DoSomething
}

For a long time, this was my standard code until I started using VSCode and got the tip from PSScriptAnalyzer to use it differently. Like that:

$Process = Get-Process
if ($null -eq $Process) {
    #DoSomething
}

From the english perspective, this should be the same, but well it really isn't.

Explanation for $null comparison

When I asked Chris about it, he explained the reason with following code

if (@() -eq $null) { 'true' }else { 'false' }
if (@() -ne $null) { 'true' }else { 'false' }

Fair enough right? Full rule documentation is available here. As documentation describe it there are reasons why this should occur:

$null is a scalar. When the input (left side) to an operator is a scalar value, comparison operators return a Boolean value. When the input is a collection of values, the comparison operators return any matching values, or an empty array if there are no matches in the collection. The only way to reliably check if a value is $null is to place $null on the left side of the operator so that a scalar comparison is performed.
PowerShell will perform type casting left to right, resulting in incorrect comparisons when $null is cast to other scalar types.

Accepting this truth made me start using $null religiously on the left side of the comparison.

When it is not a good idea to have $null on the left side

I could end the article here, saying “and they lived ever after” if I wouldn't hit a problem today because of that rule. You see I started to trust that rule without even thinking about it. The moment VSCode would tell me to fix it, I would go and fix it. So any time I would see this rule popup I would fix it and go my way:

The problem is I wasn't really testing after I changed this, every time I did it. I even started to do it for some old code and simply fixed it for peace of mind. Until I noticed that one of my scripts using RunSpaces stopped working today. Let's take a look at the code that is simplified version of it:

$Object1 = @{
    Name   = 'Test1'
    Status = 1
}
$Object2 = @{
    Name   = 'Tests2'
    Status = $null
}

$Array = @($Object1, $Object2)

$Test1 = While ($Array.Status -ne $null) {
    $true
    foreach ($A in $Array) {
        $A.Status = $null
    }
}

This code merely is supposed to set $null value in Status property of two objects: $Object1 and $Object2. While of course you usually wouldn't use While for such case, but in my code I did. When you run the code above you will get $true as an output of $Test1 variable. Everything according to plan, but with one problem – $Array.Status comparison complaining that I'm using $null on the wrong side. Let's fix it. For comparison purposes, I left both loops in the code.

$Object1 = @{
    Name   = 'Test1'
    Status = 1
}
$Object2 = @{
    Name   = 'Tests2'
    Status = $null
}

$Array = @($Object1, $Object2)

$Test1 = While ($Array.Status -ne $null) {
    $true
    foreach ($A in $Array) {
        $A.Status = $null
    }
}

$Test1

$Test2 = While ($null -ne $Array.Status) {
    $true
    foreach ($A in $Array) {
        $A.Status = $null
    }
}

$Test2

Let me know when it's done? Well, actually, it will never finish. It seems that changing order around makes it an infinite loop. Totally not what I expected. I trusted PSScriptAnalyzer a bit too much on this front.

Moral

Moral of this story? Test your code after making changes, even those that seem like a minor change. I'll, of course, ask Chris to clarify this for me, and maybe he can add some workaround for PSScriptAnalyzer to not show this suggestion if it's used on Array. Make sure to follow him on Twitter. He makes it better for us, users of VSCode and PowerShell Extension.

This post was last modified on %s = human-readable time difference 16:34

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

1 month ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

2 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

7 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

11 months ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago