I've come across the following phenomenon and am absolutely bamboozled. I'm using C# 10 with nullables enabled.
default(int?) returns null as expected. The following function, however, returns whatever default(T) is
public static T? ShouldReturnNull<T>()
{
return default(T?);
}
In the case of ShouldReturnNull<int>() we get 0. Shouldn't it also return null?
I have the following code in my program where this becomes an issue:
public T?[] FindKElements(...)
{
var result = new (T, double)?[k];
// ... populate result array,
// possibly including null values...
// return an array containing only the T part or null
return result.Select(e => e is null ? default(T?) : e.Value.Item1).ToArray();
}
Is there a way to keep it this generic but with proper nulls instead when T is a value type? The compiler won't let me use null in place of default(T?).
In the absence of a where T : struct constraint, T? does not mean Nullable<T>; it means "T, but note that it won't be null in the NRT sense" - and since NRT nulls never apply to your value-type scenario: it basically just means T; and the default value of a value-type T is not null (in any sense).
In the scenario where you need "null checking" that crosses both value-type and reference-type scenarios including support for value-types without a value, then the easiest approach is usually to forget about Nullable<T> and just track:
bool), andT)separately, and explicitly; this could be via any of:
bool SomeMethod(out var T)(HasValue: bool, Value: T) SomeMethod()Maybe<T> SomeMethod()(where Maybe<T> is just a custom struct that is composed of a bool HasValue and a T Value)
This is effectively creating something akin to Nullable<T>, but which applies to all values, regardless of type. Instead of checking for null, just check .HasValue first, and if true, assume that the value is meaningful.
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