5

I'm not quite sure if this exact question is a duplicate, but I couldn't find my specific question on stackoverflow, so I guess it's not.

$true is a boolean type:

($true).getType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Boolean                                  System.ValueType

'true' is a string:

('true').gettype()

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

why is this condition true?

PS C:\WINDOWS\system32> if ('True' -eq $true) {'yes'} else {'no'}
yes

only because the string is called True just like the boolean true? If I compare it with any other string, there is a different outcome:

PS C:\WINDOWS\system32> 'hello' -eq $true
False
PS C:\WINDOWS\system32> 'true' -eq $true
True

if you do 'true' == true in C# it prints an cannot convert string to bool error and both C# and PS are based on .net and have quite the same syntax. why is there a different outcome? this seems very strange to me.

How is PowerShell evaluating 'true' to $true?

SimonS
  • 1,891
  • 1
  • 29
  • 53
  • @Matt not exactly. they all refer why is $true -eq 'string' = true, my question is why is the exact string 'true' -eq $true while any other 'string' -eq $true is false. I also saw those questions you reffered to, but they're not the same – SimonS May 20 '16 at 11:42
  • 1
    I removed it since is it not a perfect dupe. However all the answers do talk about LHS and RHS arguments and casts so the do apply. You are referring to a specific case of that so it works fine. If you read other questions that could be related you should link them here and try to explain what they did not answer your question. – Matt May 20 '16 at 11:47
  • @Matt I totally agree. the answer is the same. maybe I was just too shocked that PowerShell evaluates stuff like this so I didn't read the answers carefully enough ;-). However, for someone that searches the answer for the question "why is 'true' -eq $true" this question gives a perfect explanation now. – SimonS May 20 '16 at 11:54
  • Dupes are not bad. They are good. Helps people to get to the right information. – Matt May 20 '16 at 12:00

1 Answers1

9

In PowerShell, operator overloading is determined by the left-hand side (lhs) argument.

This means that when you supply a string as the lhs argument, the parser will attempt to convert the right-hand side (rhs) to a string as well.

When cast to a string, $true comes out as the string "True" - which, since PowerShell's string comparison operators are all case-insensitive by default, happens to equal "true".

This operation:

'true' -eq $true

Is interpreted as

'true' -eq 'True'

Which happens to be $true, satisfying your if condition.


With $true, this also happens to work the other way around, because a non-empty string, when converted to a boolean, evaluates to $true:

In other words

$true -eq 'true'

Is interpreted as

$true -eq $true

This can lead to confusion, since the string "false" will incidentally also be evaluated as $true, simply because the string "false" is not empty:

PS C:\> $true -eq "true"
True
PS C:\> $true -eq "false"
True
PS C:\> $true -eq ""
False
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • `$true -eq 'true'` is also true. so Powershell can also convert a string to a boolean if it's the same value as the boolean? – SimonS May 20 '16 at 11:28
  • Correct - non-empty strings evaluate to `$true`, empty strings to `$false` – Mathias R. Jessen May 20 '16 at 11:32
  • It can seem a bit counterintuitive at first, but once you *know* that the operator is always determined by the **lhs** type, you can easily predict the behavior, so yes, I'd say quite nice :) – Mathias R. Jessen May 20 '16 at 11:34