区分泛型方法中的 null 和默认值

Differentiate between null and default in generic method

提问人:codymanix 提问时间:7/18/2023 更新时间:7/18/2023 访问量:56

问:

我有一个支持所有类型的方法,我想检查值是否为 null,但仅适用于引用类型,对于值类型,这种检查没有意义。 由于此方法位于调用树的深处,因此仅复制引用类型的方法并在那里使用类约束会很复杂。

void Foo<T>(T a)
{
   // check for null for reference types only
   if (a == null) 
   {
   }
}
C# 泛型 null 默认值

评论

1赞 canton7 7/18/2023
您正确编写的代码可以执行您想要的操作。你的问题到底是什么?
0赞 canton7 7/18/2023
...或者您是否担心可为 null 的值类型?
0赞 Tim Schmelter 7/18/2023
@canton7:嗯,他说他只想对引用类型进行此检查。例如,可为 null 的类型可以为 null,但不是引用类型。 如我的回答所示处理它。Type.IsValueType
2赞 canton7 7/18/2023
OP 实际上并没有这么说——他们说“对于值类型,这种检查没有意义”,它根本不考虑可为 null 的值类型。因此我的问题。
0赞 DavidG 7/18/2023
“对于值类型,这没有意义” - 我不敢苟同,是一种值类型,可以为 null。我认为这有点XY问题,或者可能是代码味道。int?

答:

4赞 Tim Schmelter 7/18/2023 #1

如果要“仅检查引用类型的 null”,则可以使用 Type.IsValueType

void Foo<T>(T a)
{
    bool isReferenceType = !typeof(T).IsValueType;
    if (isReferenceType && a == null)
    {
    }
}

因此,可为空的类型(它们是结构,因此是值类型)即使返回也不会通过此检查。我想这是预期的行为。a == nulltrue

4赞 canton7 7/18/2023 #2

如果是值类型(并且不是可为 null 的值类型,例如 ),则测试仍然完全有效:测试永远不可能,并且整个语句将被运行时优化。Tint?a == nulla == nulltrueif

在 SharpLab 上查看

如果是可为 null 的值类型,则当 的值为 (例如 )。Ta == nullanullFoo<int?>(null)

if can 是一个可以为 null 的值类型,并且您不想输入 if is ,那么 Tim Schmelter 的答案会做你想要的,但会有点低效(尽管下一个 .NET 版本将显着改进这一点)。Tifanull