Home > database >  Why I can't return a generic nullable value type and nullable reference type?
Why I can't return a generic nullable value type and nullable reference type?

Time:10-17

I have a method that should return a nullable reference type or a nullable value type:

   private static T? FooValueOrReferenceType<T>(string input)
   { 
       return null;
       // the code above show this error 
       // Cannot convert null to type parameter 'T' because it could be
       // a non-nullable value type. Consider using 'default(T)' instead.
   }

I don't understand why I cant return null, since I have enabled nullable value types in the project

I know that adding constraint where T : struct, class can resolve the problem, but I want to understand why.

I noticed that this method signature:

private static T? FooValueType<T>(string input) where T : struct

compiled to:

   private static Nullable<T> FooValueType<T>([System.Runtime.CompilerServices.Nullable(1)] string input) where T : struct

and this:

private static T? FooReferenceType<T>(string input) where T : class

compiles to:

private static T FooReferenceType<T>(string input) where T : class

What's the reason behind all this?

There is some question similar to this one, but the answers are not clear for a noob like me.

CodePudding user response:

Ultimately, nullability means two fundamentally different things for reference-types and value-types. For value-types, T? means Nullable<T> - a wrapper layer around a T, with some compiler voodoo - and for reference-types, T? means simply T, but with some additional compiler context (and attributes added, to convey that intent). There is simply no way in IL of expressing these two things at the same time, and Nullable<T> and T cannot be used interchangeably in IL (even if C# makes it look like you can). Ultimately, "you just can't, IL doesn't work that way".

Your two experiments into the : class and : struct show these two incompatible variants nicely.

  •  Tags:  
  • c#
  • Related