当 T 是值类型时,default(T?) 不会 return null

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

我遇到过以下现象,完全被迷住了。我正在使用启用了可空值的 C# 10。

default(int?) returns 如预期的那样为空。但是,下面的函数 returns 无论如何 default(T)

public static T? ShouldReturnNull<T>()
{
    return default(T?);
}

ShouldReturnNull<int>() 的情况下,我们得到 0。它不应该 return 为空吗?

我的程序中有以下代码,这成为一个问题:

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();
}

当 T 是值类型时,有没有办法让它保持这种通用性,但使用适当的空值代替?编译器不允许我使用 null 代替 default(T?)

在没有 where T : struct 约束的情况下,T? 不是 意味着 Nullable<T>;它的意思是“T,但请注意,在 NRT 意义上它不会是 null”——并且由于 NRT 空值 永远不会应用 到您的 value-type 场景:基本上就是T的意思; value-type T 的默认值不是 null (在任何意义上)。

在您需要跨越value-type和reference-type场景的“空检查”的场景中包括 支持没有值的 value-types,那么最简单的方法通常是忘记 Nullable<T> 而只跟踪:

  1. 我有值吗(bool),
  2. 值是多少 (T)

分别,并明确;这可以通过以下任何方式:

  • bool SomeMethod(out var T)
  • (HasValue: bool, Value: T) SomeMethod()
  • Maybe<T> SomeMethod()

(其中 Maybe<T> 只是一个由 bool HasValueT Value 组成的自定义 struct

这实际上是在创建类似于 Nullable<T> 的东西,但它适用于所有值,无论类型如何。不是检查 null,而是首先检查 .HasValue,如果 为真,则假设该值是有意义的。