Version Used: master
Steps to Reproduce:
using System;
public class C {
void M(object g) {
_ = g is Nullable<int>; // ok
_ = g is int?; // ok
_ = g switch { Nullable<int> => 0 }; // CS8116
_ = g switch { int? => 0 }; // syntax error
switch (g) { case Nullable<int>: break; } // CS8116
switch (g) { case int?: break; } // syntax error
}
}
Expected Behavior: either
int? type patterns as well.@alrz The issue seems more deeper than this.
https://sharplab.io/#v2:EYLgtghgzgLgpgJwDQxAgrgOyQExAagB8ABAJgEYBYAKBoEtMYB+AAgA8WBeFzdAGz4BuGgGEAdAFkAFGwCUw2tWIBmFsXIA2NaRYiaAbxotja1eq3EALC2kB7YACs4AYxgsA5rKMnD1E/7VyAE4pdxY6KBYAOX4+CGA+OAAeBhgAPnlvAMCQsIjwxiZMv2yc0PDI1OL/AF8aGqA
Nullable<T> doesn't work like other structs. IIRC, it's not possible to have a boxed Nullable<T>, you either get T or null. So it's not possible for an object to be Nullable<T> and the test will always fail. You should always test for the underlying value type instead.
int? i = 123;
object o = i;
Console.WriteLine(o.GetType()); // prints System.Int32
int? i = null;
object o = i;
Console.WriteLine(o is null); // prints True
@HaloFour Then I'd expect CS0184 warning.
@Youssef1313
Why should the compiler permit it at all if it's not possible? The error message states pretty clearly why you can't match against an NVT and what you should do instead.
@HaloFour I wasn't clear enough. I meant for the case where the compiler currently allows it. Like in this SharpLab sample (only the first two lines within C.M method).
@Youssef1313
Oh, yes, I'd agree, it should be added as a warning wave if it is not currently. Note that SharpLab does not run in "strict" mode so you might need to check elsewhere.
So if is int? and is int are identical this could be actually by design. The error clearly states that
error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
So it may be helpful to produce the same error on int? syntax as well.
Actually I take that back, it does seem that isinst Nullable<T> will match a boxed T, but only if it's not null. So this is a language limitation, and probably because it's pointless to match an int? if the pattern can only succeed if the operand is int?
I see two areas for improvement:
int? when the same would be reported for Nullable<int>int? to intAdd a code fix for this error to change int? to int
Rider does fade out ? in that expression and suggest to remove. In order for this to work in type patterns, I think the parser needs to be adjusted so we have the correct node in place.
c#
_ = g is Nullable<int>; // ok
_ = g is int?; // ok
These are not pattern-matching operations. This is the old is-type operator. It would be a breaking change to make this kind of long-accepted code an error.