Forum Discussion
Powershell: how to use an if condition with true false
- Aug 12, 2022
PowerShell is not strongly-typed language like C#, where the compiler wouldn't even let you run a test like [bool] -eq [string]. Where PowerShell does allow such operations, they come with behaviours you need to know about.
What your first test ($Stat -eq 'fal') is testing is for the existence (i.e. present and not null) of the right of the operator - since the types themselves don't match - and comparing that to the value on the left. So, rather than:
$Stat -eq 'fal';
You're actually comparing (since 'fal' both exists and is not null):
$Stat -eq $true;
Hence the result is $true.
Here's my own example illustrating this very point using an even more complex type on the right-hand side:
Now, if you swap the values around, you'd expect to get the same outcome, but you don't. This is because PowerShell is now testing for equality against the complex ActiveDirectorySite class, which the Boolean isn't going to match (since the test is something called a reference equality test - but this isn't important.)
So, this brings me to the crux of your issue: how can you reliably test a Boolean against another Boolean? (as distinct from your example that is a Boolean against a String.)
I'd posit two basic ways though there are more:
- Swap the Boolean to be on the right side of the operator, with the object you're comparing to the left;
- Use the .NET .Equals() method on the Boolean object to assess the object being checked.
PowerShell's implicit existence testing can be quite a handy feature, but in the case of working with the Boolean type also requires a bit more care - and testing - to avoid unintended outcomes.
Cheers,
Lain
PowerShell is not strongly-typed language like C#, where the compiler wouldn't even let you run a test like [bool] -eq [string]. Where PowerShell does allow such operations, they come with behaviours you need to know about.
What your first test ($Stat -eq 'fal') is testing is for the existence (i.e. present and not null) of the right of the operator - since the types themselves don't match - and comparing that to the value on the left. So, rather than:
$Stat -eq 'fal';
You're actually comparing (since 'fal' both exists and is not null):
$Stat -eq $true;
Hence the result is $true.
Here's my own example illustrating this very point using an even more complex type on the right-hand side:
Now, if you swap the values around, you'd expect to get the same outcome, but you don't. This is because PowerShell is now testing for equality against the complex ActiveDirectorySite class, which the Boolean isn't going to match (since the test is something called a reference equality test - but this isn't important.)
So, this brings me to the crux of your issue: how can you reliably test a Boolean against another Boolean? (as distinct from your example that is a Boolean against a String.)
I'd posit two basic ways though there are more:
- Swap the Boolean to be on the right side of the operator, with the object you're comparing to the left;
- Use the .NET .Equals() method on the Boolean object to assess the object being checked.
PowerShell's implicit existence testing can be quite a handy feature, but in the case of working with the Boolean type also requires a bit more care - and testing - to avoid unintended outcomes.
Cheers,
Lain
Understood why below is dangerous:
$Stat = 'False' #simulation of variable value can be of type string at times and so a direct 'if' on it yields wrong result.
if($Stat){Write-Host "if executed"}else{Write-Host "else block"}
A followup:
Though the swap trick seems to work however the "equals" method is not usable for my case because, my variable at times can have string at times (it's fetched from another source and by the time it reaches my code block, it can be either string or boolean and that's where ".Equals" doesn't give the desired result.
I understand from .NET's point of view, they both are different so it's all right. However the swap trick also yields undesired result
$Stat = 'False'
$True -eq $Stat
> True #how do I get here False?
Typecasting also doesn't help as
[bool]'False' is also True
Whether my variable value comes a string or boolean, I want the 'if' block to be executed only if it's really True (irrespective of the data type)