一般答案和经验法则:如果您有选择(例如,编写自定义序列化程序)在不同于object
-的其他管道中处理Nullable 并使用其特定属性,请执行此操作并使用Nullable特定属性。因此从一致的观点来看HasValue
应该是首选。一致的想法可以帮助您编写更好的代码,而不必花费太多时间在细节上。例如,第二种方法会有效很多倍(主要是因为编译器内联和装箱,但是数字仍然非常有表现力):
public static bool CheckObjectImpl(object o)
{
return o != null;
}
public static bool CheckNullableImpl<T>(T? o) where T: struct
{
return o.HasValue;
}
基准测试:
BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
[Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0
Clr : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1648.0
Core : .NET Core 4.6.25009.03, 64bit RyuJIT
Method | Job | Runtime | Mean | Error | StdDev | Min | Max | Median | Rank | Gen 0 | Allocated |
-------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|
CheckObject | Clr | Clr | 80.6416 ns | 1.1983 ns | 1.0622 ns | 79.5528 ns | 83.0417 ns | 80.1797 ns | 3 | 0.0060 | 24 B |
CheckNullable | Clr | Clr | 0.0029 ns | 0.0088 ns | 0.0082 ns | 0.0000 ns | 0.0315 ns | 0.0000 ns | 1 | - | 0 B |
CheckObject | Core | Core | 77.2614 ns | 0.5703 ns | 0.4763 ns | 76.4205 ns | 77.9400 ns | 77.3586 ns | 2 | 0.0060 | 24 B |
CheckNullable | Core | Core | 0.0007 ns | 0.0021 ns | 0.0016 ns | 0.0000 ns | 0.0054 ns | 0.0000 ns | 1 | - | 0 B |
基准代码:
public class BenchmarkNullableCheck
{
static int? x = (new Random()).Next();
public static bool CheckObjectImpl(object o)
{
return o != null;
}
public static bool CheckNullableImpl<T>(T? o) where T: struct
{
return o.HasValue;
}
[Benchmark]
public bool CheckObject()
{
return CheckObjectImpl(x);
}
[Benchmark]
public bool CheckNullable()
{
return CheckNullableImpl(x);
}
}
https://github.com/dotnet/BenchmarkDotNet使用
PS。人们说建议“由于始终如一的想法而首选HasValue”是无关的和无用的。您可以预测其性能吗?
public static bool CheckNullableGenericImpl<T>(T? t) where T: struct
{
return t != null; // or t.HasValue?
}
PPS人们继续减负,但是没有人试图预测PPS的表现CheckNullableGenericImpl
。而且那里的编译器不会帮助您替换!=null
为HasValue
。HasValue
如果您对性能感兴趣,应直接使用。