-2

This code:

public T Foo<T>()
    where T : class?
{
    return null;
}

Gives a following error:

A null literal introduces a null value when 'T' is a non-nullable reference type

I don't see why we can't return null when we say that T can be nullable. If we additionally try to return T? we will get an error that T has to be non-nullable.

It seems it's kind of impossible to have a nullable constraint and return a nullable result at the same time.

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • 6
    How often do you want to post the exact same question? See https://stackoverflow.com/questions/59631254/inconsistent-behavior-in-c-sharp-8-nullable-reference-type-handling-with-generic and https://stackoverflow.com/questions/59630532/what-does-class-class-with-question-mark-mean-in-a-c-sharp-generic-type-const – MakePeaceGreatAgain Jan 07 '20 at 15:34
  • 2
    It is not exact the same question even though it might seem like this – Ilya Chernomordik Jan 07 '20 at 15:35
  • 2
    Well, I've already answered [this](https://stackoverflow.com/a/59631044/4728685) There is a known [issue](https://github.com/dotnet/csharplang/issues/2840) with this constraint – Pavel Anikhouski Jan 07 '20 at 15:36
  • @PavelAnikhouski, in a way. There is not really an answer in these quesitons on github. And I'd like to know how it is possible to return nullable with nullable constraint, which seem impossible – Ilya Chernomordik Jan 07 '20 at 15:37
  • Obviously as of the current implementation it simply is not possible because of the mentioned bug. Of course there´s no answer on github, because that bug isn´t solved. So what do you expect here? – MakePeaceGreatAgain Jan 07 '20 at 15:38
  • I have not seen anyone acknowledged this is a bug and that it will be fixed, or there is some explanation to it – Ilya Chernomordik Jan 07 '20 at 15:40
  • And it actually does not seem to be the case, don't really understand the attitude. An ordinary valid question, and @canton7 gave an answer that makes sense which means it does not seem this is a bug. So what I expect is a nice answer like the one given, and not strange comments really – Ilya Chernomordik Jan 07 '20 at 15:42
  • @IlyaChernomordik I've added a possible solution for that in linked answer. As other comments say, I'll get an answer when it'll be fixed – Pavel Anikhouski Jan 07 '20 at 15:43
  • @PavelAnikhouski It seems as per the given answer that it actually makes sense that it is not allowed to it this way. So it does not really seem like a bug since constraint means "class can be null". Then everything makes sense – Ilya Chernomordik Jan 07 '20 at 15:48

2 Answers2

3

Imagine you call:

string result = Foo<string>();

result now contains null. But it's a string, which is not nullable.

The compiler is warning you that Foo<T> may be called where T is not nullable, and returning null in this case would be unexpected.

Note that where T : class? means that T may be nullable, but it also might not be. Both string and string? are allowed. I don't believe there's any way to say "T must be nullable".


If you're trying to say:

  1. T is allowed to be nullable
  2. When T is non-nullable, then this type can still return null

Then you can write:

[return: MaybeNull]
public T Foo<T>()
    where T : class?
{
    return null!;
}

SharpLab

Note that MaybeNull only applies to the method's contract and not its body, when is why we need to return null!. However you can see in the SharpLab link above that the caller string result = Foo<string>(); gets the correct warning.

canton7
  • 37,633
  • 3
  • 64
  • 77
  • 1
    well, should not we get a warning since we said `class?` and `string` is not `string?` – Ilya Chernomordik Jan 07 '20 at 15:38
  • @IlyaChernomordik No. `where T : class?` means "`T` must be a class, and *may* be nullable". It means `T` can be e.g. both `string` and `string?`. If you say `where T : class`, then `T` cannot be `string?` – canton7 Jan 07 '20 at 15:41
  • 1
    Thanks for the answer, I got it now. 'class?' means it can be nullable, but not necessarily nullalbe – Ilya Chernomordik Jan 07 '20 at 15:43
0

Let's start from basic. Let say you have a reference type variable that allows it to have null value. But your program design requires it to be not null all times, if a null value is encountered, it is mostly likely to get the NullReferenceException.

To avoid such design issues, The NullableReference types was introduced. Means if a reference type is allowed to have null you should mark it as Nullable and any usage should check for null value before using it. If checking is not found then compiler will generate a warning.

If you read this introductory article on NullableReferenceTypes You will get the fair idea of what is the intent of this new feature.

vendettamit
  • 14,315
  • 2
  • 32
  • 54
  • Hey, thanks for the answer. The whole confusion I got was because I thought that `class?` means it must be nullable. So when it's clear it means can be nullable, all this makes sense – Ilya Chernomordik Jan 07 '20 at 15:59