I like to use pattern-matching
on a nullable int
i.e. int?
:
int t = 42;
object tobj = t;
if (tobj is int? i)
{
System.Console.WriteLine($"It is a nullable int of value {i}");
}
However, this results in the following syntax errors:
'i)' is marked with a red squiggly line.
The expression compiles when using the old operator is
:
int t = 42;
object tobj = t;
if (tobj is int?)
{
System.Console.WriteLine($"It is a nullable int");
}
string t = "fourty two";
object tobj = t;
if (tobj is string s)
{
System.Console.WriteLine($@"It is a string of value ""{s}"".");
}
Also works as expected.
(I'm using c#-7.2 and tested with both .net-4.7.1 and .net-4.6.1)
I thought it had something to with operator precedence. Therefore, I have tried using parenthesis at several places but this didn't help.
Why does it give these syntax errors and how can I avoid them?
Pattern Matching works by "reading" through text strings to match patterns that are defined using Pattern Matching Expressions, also known as Regular Expressions. Pattern Matching can be used in Identification as well as in Pre-Classification Processing, Page Processing, or Storage Processing.
You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false .
C# pattern matching provides more concise syntax for testing expressions and taking action when an expression matches. The " is expression" supports pattern matching to test an expression and conditionally declare a new variable to the result of that expression.
The Nullable type allows you to assign a null value to a variable. Nullable types introduced in C#2.0 can only work with Value Type, not with Reference Type. The nullable types for Reference Type is introduced later in C# 8.0 in 2019 so that we can explicitly define if a reference type can or can not hold a null value.
The type pattern in its various forms: x is T y
, case T y
etc, always fails to match when x
is null
. This is because null
doesn't have a type, so asking "is this null
of this type?" is a meaningless question.
Therefore t is int? i
or t is Nullable<int> i
makes no sense as a pattern: either t
is an int
, in which case t is int i
will match anyway, or it's null
, in which case no type pattern can result in a match.
And that is the reason why t is int? i
or t is Nullable<int> i
are not, and probably never will be, supported by the compiler.
The reason why you get additional errors from the compiler when using t is int? i
is due to the fact that, e.g. t is int? "it's an int" : "no int here"
is valid syntax, thus the compiler gets confused over your attempts to use ?
for a nullable type in this context.
As to how can you avoid them, the obvious (though probably not very helpful) answer is: don't use nullable types as the type in type patterns. A more useful answer would require you to explain why you are trying to do this.
Change your code into:
int t = 42;
object tobj = t;
if (tobj is Nullable<int> i)
{
Console.WriteLine($"It is a nullable int of value {i}");
}
This produces the more helpful:
Others (user @Blue0500 at github ) have tagged this behaviour as a bug Roslyn issue #20156. Reacting to Roslyn issue #20156, Julien Couvreur from Microsoft has said he thinks it is by design.
Neal Gafter from Microsoft working on Roslyn has also said better diagnostics are wanted for use of nullable type is switch pattern.
So, the error message can be avoided by using:
int t = 42;
object tobj = t;
if (tobj == null)
{
Console.WriteLine($"It is null");
}
else if (tobj is int i)
{
Console.WriteLine($"It is a int of value {i}");
}
Except for issues when parsing tobj is int? i
, this still leaves the question why is tobj is int? i
or tobj is Nullable<int> i
not allowed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With