public readonly struct Foo<T>
{
// ...
public T Value { get; }
}
public static Foo<string?> Bar(Foo<string?> foo)
{
if (foo.Value is null) { /* Something */ }
else { /* Some other thing */ }
return foo;
}
public static void Main()
{
var foo1 = new Foo<string>("s");
var ret1 = Bar(foo1); // Warns because foo1's type parameter is not nullable
var foo2 = new Foo<string?>("s");
var ret2 = Bar(foo2); // Ok because foo2's type parameter is nullable
}
Foo<string?>
and Foo<string>
?T
of the returning Foo<T>
will be the same as the nullability of T
of the parameter Foo<T>
?For a Foo<string?> Bar(Foo<string?> foo)
method, the type parameter of the accepted foo has no relation to the type parameter of the returned foo. And currently, there is no way to annotate the intended relationship of their nullabilities.
Type parameter T
in a generic Foo<T> Bar<T>(Foo<T> foo)
method, however, would allow us to share the nullability and we could add a generic type constraint like where T : MyType?
in order to use type-specific functionality.
Unfortunately, we can't write where T : string?
, because C# does not allow sealed classes to be used as type constraints. This is reasonable as it wouldn`t make sense before - why would we design the method as generic at the first place if there is only one type we can use anyway? Well, with C# 8 and nullable reference types are out in the wild, I think we may have a valid reason now. Maybe the team can lift this restriction as they lifted it for enums.
To answer my own question:
As a side note: Even though C# doesn't let us use sealed types as type constraints, IL does. So if weaving is an option, we can actually add sealed type constraints to generic type parameters. A solution like ExtraConstraints can be extended to provide this functionality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With