2

this code complains

public static T? Foo<T>()
{
   return null;
}

with

Error CS0403
Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.

But aren't I telling the compiler it can be null?

If T is int, then I want the answer to be null, not 0.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
MrD at KookerellaLtd
  • 2,412
  • 1
  • 15
  • 17

1 Answers1

4

Because T is unconstrained in your case, and for unconstrained (neither to struct nor to class) generic type parameters T - T? is handled differently for value types and reference types. From the docs:

  • If the type argument for T is a reference type, T? references the corresponding nullable reference type. For example, if T is a string, then T? is a string?.
  • If the type argument for T is a value type, T? references the same value type, T. For example, if T is an int, the T? is also an int.
  • If the type argument for T is a nullable reference type, T? references that same nullable reference type. For example, if T is a string?, then T? is also a string?.
  • If the type argument for T is a nullable value type, T? references that same nullable value type. For example, if T is a int?, then T? is also a int?.

So for Foo<int> actual signature will be int Foo<int>, hence the error.

If it is suitable for you - constrain T to be either struct or class.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • ah ok....bit odd...I think for the moment I'll constrain it to be a class. – MrD at KookerellaLtd Apr 28 '23 at 11:25
  • @MrDatKookerellaLtd Yep. It is a bit odd and mainly due to the fact that nullablle reference types perform some kind of type erasure, i.e. compared to nullable value types which are actually `Nullable` they are not represented with different type. – Guru Stron Apr 28 '23 at 12:15
  • @MrDatKookerellaLtd also check [this sharplab snipped](https://sharplab.io/#v2:CYLg1APgAgTAjAWAFCwAQFkCeAVApgZwBcA5AVwBtzkBvZVe1ABwCcBLANwENDdVsBpXJgD8fAoQDCAewB2RZp1YzC+ADwChAPgAUGzKgDWQgDR9BI1DIrlOAI3K5zqALyXrASjoNvAdwAWuMy8eqggqPKkAMaELpqGQgDcXvTJTGxcPGZConhE0nKECkoq6uY6IUaYpnqiVpR2Dk6udeSeSN6+AUFZ+mFoznGVSe0MqSwc3LxQACxiROi4hH5SwNpt3rQjHahczKiswC6oAKzD2/S7qDGuuZKy8orK+NoH7mfnAPQfqD6slJZSGKRKQAW0Yf1wqW8Xx2nD2hDgR1u+QexWeL2Uwncr3e20u+CR4hRhUeKm0ACJyW9UgBfZA0oA=) it can be a nice workaround in some cases. – Guru Stron Apr 28 '23 at 12:15