如何在同一个方法中处理 notnull 类和值类型?

Tes*_*ill 5 c# null .net-core nullable-reference-types

请注意,整个问题假设可空上下文是 NET 6 中的默认值。

我想编写一个方法Read,它接受不可为空类型(即结构或类)并输出该结构或类的可为空版本。像这样的东西(显然它不仅仅返回默认值,但不需要使这个复杂化):

public static T? Read<T>()
{
    return default; //should return null
}
Run Code Online (Sandbox Code Playgroud)

此示例方法应该返回 null,实际上它对于类、可为 null 的类和可为 null 的值类型返回 null,但对于值类型则不然:

Console.WriteLine(null == Read<string>()); //true
Console.WriteLine(null == Read<string?>()); //true
Console.WriteLine(null == Read<int>()); //false
Console.WriteLine(null == Read<int?>()); //true
Run Code Online (Sandbox Code Playgroud)

我想要一个对于所有这些情况都返回 true 的方法。我已经尝试了对 T 的一大堆约束。我觉得notnull约束应该有效,但事实并非如此。

我可以创建两种方法,一种限制为struct(即值类型),一种限制为class(即不可为空的引用类型)。以下作品:

public static T? ReadValue<T>()  where T: struct
{
    return null; //does return null
}

public static T? ReadRef<T>()  where T: class
{
    return null; //does return null
}
Run Code Online (Sandbox Code Playgroud)

但是,正如您所看到的,这两种方法将是相同的,没有约束和不同的名称(这是必需的,因为它们具有相同的签名)。因此,我必须为此制定两种不同的方法,这似乎很愚蠢。

对于上下文:我知道这种情况的混乱部分是由在Nullable<T>引擎盖下表示的可空值类型引起的,而可空类只是由编译器跟踪。我只是想知道是否有办法避免这种情况。

Gur*_*ron 0

AFAIK 这是不可能的,原因如下:

  1. 没有显式提供参数的调用的重载解析(对于显式提供泛型类型参数的调用,您可以使用类似于此问题的答案中指定的方法 - 请自行查看) - 请参阅Jon Skeet的精彩博客文章。

  2. 当泛型类型参数T不受约束时,class编译struct器将T?区别对待值和引用类型,并且值类型T?将等于T(请参阅答案)。