Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

default(T?) does not return null when T is a value type

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?).

like image 951
Kisar Avatar asked Jun 29 '26 21:06

Kisar


1 Answers

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:

  1. do I have a value (bool), and
  2. what is the value (T)

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.

like image 170
Marc Gravell Avatar answered Jul 01 '26 18:07

Marc Gravell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!