Consider this class
public sealed record IdValuePair<TId, TValue>
{
public IdValuePair(TId id, TValue value)
{
EnsureArg.HasValue(value, nameof(value));
Id = id;
Value = value;
}
public IdValuePair(TValue value)
{
EnsureArg.HasValue(value, nameof(value));
Id = default!;
Value = value;
}
public TId Id { get; }
public TValue Value { get; }
}
Why is it that if I add the generic constraint
where TId : notnull
I am unable to do this assignment, due to the below error:
Id = default;
CS8601 Possible null reference assignment.
Doesn't the notnull
constraint ensure that TId
is not null?
CodePudding user response:
Consider IdValuePair<string, int>
, the default value for string is null
. So assigning null to the Id would clearly be illegal, since you promised that it should not be null.
Adding the constraint where TId : notnull
constraint would only prevent declarations like IdValuePair<string?, int>
. So we would go from a "Possible null reference assignment" to a "Definite null reference assignment".
There is, as far as I know, no generic constraint that restricts a type to either a nullable reference or nullable struct. And this can cause problems in some generic code.
There are a few possible options:
- use a struct-constraint. Value types can never be null, so assigning default should be perfectly safe.
- Use a new-constraint, and create a new object rather than using
default
- Create your own
Maybe<T> / Option<T> / Nullable<T>
type.