Roslyn: T? is not allowed as a type pattern

Created on 28 Sep 2020  路  11Comments  路  Source: dotnet/roslyn

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

  • No error in all cases
  • CS8116 for int? type patterns as well.
Area-Compilers Concept-Diagnostic Clarity New Feature - Warning Waves

All 11 comments

@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:

  1. Report CS8116 for use of int? when the same would be reported for Nullable<int>
  2. Add a code fix for this error to change int? to int

Add 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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OndrejPetrzilka picture OndrejPetrzilka  路  3Comments

DavidArno picture DavidArno  路  3Comments

ashmind picture ashmind  路  3Comments

MadsTorgersen picture MadsTorgersen  路  3Comments

AdamSpeight2008 picture AdamSpeight2008  路  3Comments