空传播算子的性能与编译
Performance and compilation of null propagation operator
这里特指我要重写的一些C#属性
原始属性之一的示例:
public double? PartQuantity
{
get
{
if( MaintenanceRequestPart != null )
return MaintenanceRequestPart.ReportedQuantity.HasValue
? (double?)MaintenanceRequestPart.ReportedQuantity.Value
: null;
return null;
}
}
这将更改为:
public double? PartQuantity => MaintenanceRequestPart?.ReportedQuantity;
注1: MaintenanceRequestPart
可以为空
注 2: MaintenanceRequestPart.ReportedQuantity
是一个可为 null 的 double
这会节省还是增加一些 operations/branching/overhead?我很好奇什么?运算符一旦变成中间语言,实际上就在幕后进行翻译。
这很好。唯一的区别是它将在 IL 级别 上复制此变量的引用。所以这基本上意味着:
public double? PartQuantity => MaintenanceRequestPart?.ReportedQuantity;
等同于:
public double? PartQuantity
{
get
{
var value = MaintenanceRequestPart;
return value == null ? null : value.ReportedQuantity;
}
}
为什么要进行额外的复制?答案很简单——如果这个值是从不同的线程访问的,则为原子决策捕获值。这在处理事件时非常有用(因此它不会在“?”运算符中间抛出 NullReferenceException):
public event EventHandler OnSomethingHappened;
...
OnSomethingHappened?.Invoke(this, new EventArgs());
但是,不要害怕,它不会对性能产生合理的影响。
结论:你可以在不丢失任何东西的情况下进行重构
这里特指我要重写的一些C#属性
原始属性之一的示例:
public double? PartQuantity
{
get
{
if( MaintenanceRequestPart != null )
return MaintenanceRequestPart.ReportedQuantity.HasValue
? (double?)MaintenanceRequestPart.ReportedQuantity.Value
: null;
return null;
}
}
这将更改为:
public double? PartQuantity => MaintenanceRequestPart?.ReportedQuantity;
注1: MaintenanceRequestPart
可以为空
注 2: MaintenanceRequestPart.ReportedQuantity
是一个可为 null 的 double
这会节省还是增加一些 operations/branching/overhead?我很好奇什么?运算符一旦变成中间语言,实际上就在幕后进行翻译。
这很好。唯一的区别是它将在 IL 级别 上复制此变量的引用。所以这基本上意味着:
public double? PartQuantity => MaintenanceRequestPart?.ReportedQuantity;
等同于:
public double? PartQuantity
{
get
{
var value = MaintenanceRequestPart;
return value == null ? null : value.ReportedQuantity;
}
}
为什么要进行额外的复制?答案很简单——如果这个值是从不同的线程访问的,则为原子决策捕获值。这在处理事件时非常有用(因此它不会在“?”运算符中间抛出 NullReferenceException):
public event EventHandler OnSomethingHappened;
...
OnSomethingHappened?.Invoke(this, new EventArgs());
但是,不要害怕,它不会对性能产生合理的影响。
结论:你可以在不丢失任何东西的情况下进行重构