0

I have a project in ASP.NET Core 6.

I have the <Nullable>enable</Nullable> setting in the project.

I have the following class:

public class ResponseResult<T> 
{
    public T? Result{ get; set; }
}

I can instantiate the class with a nullable or non-nullable generic parameter and the compiler does not generate a warning about it:

var a = new ResponseResult<WeatherForecast>();
var a2 = new ResponseResult<WeatherForecast?>();

My question is: why doesn't the compiler generate an error in the first case?

Since public T? Result{ get; set; } is nullable, shouldn't I be allowed to instantiate this class only with a nullable generic parameter?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
MiBuena
  • 451
  • 3
  • 22

1 Answers1

0

This is the expected behaviour. I don't see why it should be a problem.

For <WeatherForecast>, T is WeatherForecast and T? is WeatherForecast?.

For <WeatherForecast?>, both T and T? are WeatherForecast?.

When you declared the class this way:

public class ResponseResult<T> 
{
    public T? Result{ get; set; }
}

You didn't say "T must be nullable for the entire ResponseResult class", you said "Result is a property of type T, and the property is nullable if T is a reference type".

As far as I know, there is no way to actually constrain the generic type argument to have to be nullable. There is no need, as you can just use T? inside the class.

Petrusion
  • 940
  • 4
  • 11
  • Yes, I also didn't a way to put a constraint the generic parameter to be nullable. Maybe they skipped it for a readon. Now - the compiler seems ok with my solution, but I was wodering what the right thing to do is? If I want to write high quality code - when instantiating the class, should I pass - to hint once again to the reader that the parameter can be null? Or am I overdoing it? – MiBuena Jul 01 '22 at 13:30
  • @MiBuena As for what is actually the right thing to do here, I wouldn't use the `ResponseResult` class as it is. If T is a value type then Result will not be nullable, which is just waiting to bite you in the future as `ResponseResult` seems to rely on the ability to **not have a result**. Either constrain T to reference types with the `class` constraint, or make sure it will play nice with structs too. Either way, use non-nullable generic arguments because the nullable ones don't change anything about the class's usage. – Petrusion Jul 01 '22 at 14:52
  • @MiBuena I would also make `ResponseResult` immutable (that `set;` is just waiting to cause hard to debug problems), and *maybe* make it a struct too depending on what you are going to do with it. – Petrusion Jul 01 '22 at 14:57
  • the only thing I use this class for to wrap the result of an httpget call. It also has a bool isSuccess property and the Result property holds the value which comes from the api. If the external api throws an Exception the Result property will be null. Your suggestion to constrain it to a class is very reasonable! – MiBuena Jul 01 '22 at 17:25