-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Improve Null-Like behaviour in comparisons #10422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
|
One question is performance degradation. |
|
Good call, @iSazonov, made that change. 💖 |
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
src/System.Management.Automation/engine/runtime/Binding/Binders.cs
Outdated
Show resolved
Hide resolved
|
I played the changes a bit and found an issue: > [System.DBNull]::Value -ge [NullString]::Value
True
> [NullString]::Value -le [System.DBNull]::Value
TrueHowever, we don't consider
|
|
@daxian-dbw yeah I can see how that would arise, for sure. It is an anomaly, but it makes some sense here. With Is there a better option available for us to use here? |
|
Taking that |
|
Is there a sensible result for either comparison? In what sense is one version of a null value numerically greater or lesser than another? Or should we be doing something very unusual and always returning $false for any such comparison? In other words, should this be the case? $NullString = [NullString]::Value
$DBNull = [DBNull]::Value
$NullString -ge $DBNull # -> false
$NullString -le $DBNull # -> false
$NullString -gt $DBNull # -> false
$NullString -lt $DBNull # -> false
$DBNull -ge $NullString # -> false
$DBNull -le $NullString # -> false
$DBNull -gt $NullString # -> false
$DBNull -lt $NullString # -> falseWhile this is possible, I'm not sure it's sensible. It boils down to a pretty simple problem: what is the expected result here? In my view, it should be reasonably intuitive, and although perhaps initially surprising, I think the current behaviour makes more sense than the alternatives I can see at the moment. |
|
We could add samples for $null in the list. |
|
@iSazonov all comparisons with null-like values and $null reflect that they're equal. I'll have to verify -ge and -le but I believe they evaluate as equal in all cases. 🙂 |
|
@iSazonov updated list of what the suggested change (Personally, I don't think this makes sense; these comparisons have always worked on a slightly different basis to $NullString = [NullString]::Value
$DBNull = [DBNull]::Value
$NullString -ge $DBNull # -> false
$NullString -le $DBNull # -> false
$NullString -ge $null # -> true
$NullString -le $null # -> true
$NullString -gt $DBNull # -> false
$NullString -lt $DBNull # -> false
$NullString -gt $null # -> true (?)
$NullString -lt $null # -> false (?)
$DBNull -ge $NullString # -> false
$DBNull -le $NullString # -> false
$DBNull -ge $null # -> true
$DBNull -le $null # -> true
$DBNull -gt $NullString # -> false
$DBNull -lt $NullString # -> false
$DBNull -gt $null # -> true (?)
$DBNull -lt $null # -> false (?)I think that despite $NullString and $DBNull being not equal to each other, comparisons with Thoughts, @daxian-dbw? 🙂 |
|
@daxian-dbw @SteveL-MSFT friendly ping for review! 💖 😊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any particular reason 0 is left hand side unlike the tests below? For completeness, it seems -le should be covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that I can recall. Will add the -le test as well. 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed and pushed new commits. Also rebased since this branch is pretty old. 🙂
Handling null-like items (DBNull.Value/NullString.Value) the same way as true null here allows database-interfacing code to do numeric comparisons such as `$dbEntry.Value -gt 4` and get a sensible response of true/false depending on operator. Without this change, these operations would result in errors.
Use -ge not -eq for test For fairly plain reasons, PS doesn't consider $null as equal to zero This is only a good approximation in definitively numeric circumstances
|
The Pretty sure I have your last option there completely implemented. There should be a test confirming your point about |
|
Good point about There, the case is clear-cut: the numeric LHS should coerce the Would this need to be a separate fix?
Well, it's whatever the type's
Again, this comes from the LHS dictating the behavior (in line with what @KirkMunro says) - and the consistent implementation of that for |
|
I am happy to commit that fix separately in another PR if we prefer. Now that I see where it went wrong, it's a fairly simple asymmetry to resolve. |
Will it again a breaking change? |
|
It would technically be a breaking changing, but given that the current behavior is useless in the cases we'd be fixing, I don't expect that to be a problem. Let me try to summarize the discussion, to make sure we're on the same page:
At the very least, the cases where To put it in terms of Pester tests: Null-like as the RHS: # These currently fail and should be fixed in any event.
# $null[-like] should consistently be coerced to 0 in these cases.
0 -eq $null | Should -BeTrue
0 -ne $null | Should -BeFalse
0 -gt $null | Should -BeFalse
0 -le $null | Should -BeTrue
# These already work as expected.
0 -ge $null | Should -BeTrue
0 -lt $null | Should -BeFalseNull-like as the LHS: # Passes, and shouldn't change.
# Anything other than a null-like type on the RHS should result in $false
$null -eq 0 | Should -BeFalse
# These are currently the only cases with $null as the LHS were
# numeric interpretation works as expected:
$null -le 0 | Should -BeTrue
$null -lt 0 | Should -BeFalse
# These currently fail from a treat-null-as-0 perspective.
$null -ge 0 | Should -BeTrue
$null -lt 0 | Should -BeFalse |
|
@mklement0 Thanks for the summarization!
Difference |
|
Thanks, @iSazonov, I've removed the duplicate test from my previous comment.
I agree that it is unfortunate, but not fundamentally - asymmetrical However, we cannot change Pragmatically speaking, interpretation of LHS As for the fundamental asymmetry with PS> 2 -eq '+2'
True
PS> '+2' -eq 2
False |
|
Yeah, we can't avoid that difference. If we try to mess around with that we'll get in the way of PS's array-filtering semantics with It is also a bit confusing, but it does follow clearly defined rules -- unlike the current behaviour with |
We have been living with this for a long time. |
|
I understand your concerns there @iSazonov. But I would prefer the language behave as consistently as possible; the fewer strange exceptions to the rules are, the better. @daxian-dbw can you or the @PowerShellTeam weigh in on this aspect? It's not critical to this PR, but I feel it would make sense to take care of within the scope of this PR if we're going to do so. Quick summary: the |
|
@PowerShell/powershell-committee reviewed this and is concerned that changing this behavior will break other scenarios that rely on the variants of null to be different due to loss of information. We did not conclude on this but agreed it isn't necessary for PS7. |
|
@SteveL-MSFT is that specifically about having |
|
@PowerShell/powershell-committee has discussed this last week as part of a broader |
Please add reference to the issue. |
|
Created #11604 |
PR Summary
This changes the operator binders for
-lt/-gt(etc.) to recognise null-like values the same as it does fornull, so that it treats them as a0value when comparing to a numeric value.PR Context
Fixes #10404
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.