2

In C#8 we can now enable nullables, which means that reference types by default are considered not null by the compiler unless explicitly declared as nullable. Yet, it seems the compiler still throws a warning when trying to return a default generic with the notnull constraint. Consider the following example:

public TReturn TestMethod<TReturn>() where TReturn : notnull
{
    return default; // default is flagged with a compiler warning for possible null reference return
}

I thought maybe it would help if I also enforced that the return type must have an empty constructor, but it produces the same result:

public TReturn TestMethod<TReturn>() where TReturn : notnull, new()
{
    return default; // default is flagged with a compiler warning for possible null reference return
}

Why is the compiler flagging this line?

HotN
  • 4,216
  • 3
  • 40
  • 51
  • 1
    wait... `new()` does not mean "empty constructor" – T.S. May 20 '20 at 18:25
  • 4
    `default` still means `null` for reference types. – juharr May 20 '20 at 18:27
  • I’m pretty certain `default` will always return `null` for classes. It won’t attempt to construct a new instance, even if there’s a default constructor. – Jeremy Caney May 20 '20 at 18:29
  • @T.S.: Isn’t that exactly what the [`new()` constraint](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-constraint) suggests? “The new constraint specifies that a type argument in a generic class declaration must have a public parameterless constructor.” Or am I missing a nuance between “parameterless” and “empty”? – Jeremy Caney May 20 '20 at 18:31
  • @JeremyCaney "parameter-less" is not empty, no?... Yes – T.S. May 20 '20 at 18:33
  • 1
    @HotN: With the `new()` constraint in place, you could instead call `return new TReturn()`. – Jeremy Caney May 20 '20 at 18:34
  • 3
    @JeremyCaney "parameterless" means "has no parameters". "empty" means "has no body". I suspect that OP meant the former. – D Stanley May 20 '20 at 18:34
  • @DStanley: Interesting, thank you! It seems I’ve been sloppy with my own nomenclature here. – Jeremy Caney May 20 '20 at 18:39

1 Answers1

2

TReturn : notnull means that TReturn must be a non-nullable type (which can be either a value type or a non-nullable reference type). Unfortunately, the value of default for non-nullable reference types is still null, hence the compiler warning.

If you want the "default" for a non-nullable reference type to be whatever is created with a parameterless constructor, for example, you could do:

public TReturn TestMethod<TReturn>() where TReturn : notnull, new()
{
    return new TReturn(); 
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240