Pattern Matching Boxed Primitives Differs From Unboxed Primitive #9035
-
DescriptionPattern matching exhibits surprising behavior when values are boxed Why is this behavior a bug?I think this is a bug because Why fix?Pattern matching is very useful on loosely typed data. This kills some of the benefit because you have to type-check the target data in order to get intuitive results. More importantly, you have to know you have to type-check; otherwise, you silently get unexpected results. Real use caseSystem.Data.Common.DbCommand cmd = ...some command
object? count = await cmd.ExecuteScalarAsync();
// Surprise - this will never be true b/c `count` will be a boxed `long`
if (count is 1)
{
// do something
}
// This will be true, if count is actually the value `1` was actually returned
if (count is 1L)
{
// do something
} Reproduction Steps [Fact]
public void Boxed_Pattern_Match_Should_Match_Unboxed()
{
long val = 1L;
object valBoxed = 1L;
Assert.True(val is 1);
Assert.False(val is not 1);
Assert.True(valBoxed is 1); // fails
Assert.False(valBoxed is not 1); // fails
} Expected behaviorBoxed Actual behaviorBoxed Regression?unknown Known WorkaroundsType check the value first, (e.g. Configuration
Other informationNo response |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
This is a question related to C# language, not runtime behavior. C# compiles them into different checks. The behavior is similar to
This can't happen. Once a number is boxed, it's impractical to try every possible type.
You can also use Note that this code manually traverses every numeric type it cares about. It's necessary to explicitly do so. |
Beta Was this translation helpful? Give feedback.
This is a question related to C# language, not runtime behavior. C# compiles them into different checks.
The behavior is similar to
==
with a cast.longVariable == (long)1
will success, but(long)(object)longVariable == (long)(object)1
will throw.In other words, the pattern is interpreted at the available type information of LHS. Literal
1
will be interpreted as(object)(int)1
when LHS isobject
.This can't happen. Once a number is boxed, it's impractical to try every possible type.
You can also use
count is 1L
to provide a literal of long …