C# 在初始化属性、在if中进行null检查或合并时,哪个更有效?

C# 在初始化属性、在if中进行null检查或合并时,哪个更有效?,c#,.net,vb.net,null-coalescing,C#,.net,Vb.net,Null Coalescing,我一直在努力提高一些代码的效率,现在我想知道哪种模式更有效。出于遗留原因,该解决方案在VB.NET和C#中都有代码 我已经加入了我们现有的两种方法的VB和C版本 其思想是,如果访问了Foo属性并且\u Foo为空,那么它将被设置为一个新对象,任何后续请求都将访问该对象,而不是每次创建一个新对象 我知道编译器和JIT在幕后做了一些聪明的事情,但我不确定哪种方法更有效 选项1:合并值。VisualStudio一直建议在某些地方进行合并,因此这使我认为该操作是相当优化的。但是,每次我们得到foo 选项

我一直在努力提高一些代码的效率,现在我想知道哪种模式更有效。出于遗留原因,该解决方案在VB.NET和C#中都有代码

我已经加入了我们现有的两种方法的VB和C版本

其思想是,如果访问了
Foo
属性并且
\u Foo
为空,那么它将被设置为一个新对象,任何后续请求都将访问该对象,而不是每次创建一个新对象

我知道编译器和JIT在幕后做了一些聪明的事情,但我不确定哪种方法更有效

选项1:合并值。VisualStudio一直建议在某些地方进行合并,因此这使我认为该操作是相当优化的。但是,每次我们得到
foo
选项2:比较
\u foo
null
,然后仅在需要时分配给
\u foo

我确信两者在速度上几乎没有什么区别,但我很好奇在低得多的层次上如何处理它们

Private\u foo As列表(福巴的)
专用条作为字符串
私人(福巴)2 As名单
Private_bar2作为字符串
公共财产Foo As清单(Fubar)
得到
_foo=If(_foo,新列表(Fubar))
返回(u foo)
结束
设置(值为列表(Fubar))
_foo=值
端集
端属性
作为字符串的公共属性栏
得到
_bar=If(_bar,String.Empty)
返回条
结束
设置(值为字符串)
_bar=值
端集
端属性
公共财产Foo2作为清单(Fubar)
得到
如果_foo2什么都不是,那么_foo2=新列表(Fubar)
返回2
结束
设置(值为列表(Fubar))
_foo2=值
端集
端属性
公共属性Bar2作为字符串
得到
如果_bar2为空,则_bar2=String.Empty
返回2
结束
设置(值为字符串)
_bar2=数值
端集
端属性
private List\u foo;
私人字符串(u bar),;
私人名单2;
私有字符串_bar2;
公开名单
{
得到
{
_foo=(_foo??新列表());
返回(u foo);;
}
设置
{
_foo=价值;
}
}
公共字符串栏
{
得到
{
_bar=(_bar??string.Empty);
返回条;
}
设置
{
_bar=值;
}
}
公众名单2
{
得到
{
如果(_foo2==null){u foo2=new List();}
返回2;
}
设置
{
_foo2=值;
}
}
公共字符串条2
{
得到
{
如果(_bar2==null){u bar2=string.Empty;}
返回2;
}
设置
{
_bar2=数值;
}
}

我们开始了;这里的
IsEmpty
告诉我们在
get
操作之前它是否为
null
,即它使用了哪个分支

我的结论是:

  • 如果该值通常有一个值,
    *2
    方法更好
  • 如果该值通常还没有值,则没有真正的区别
  • 但这些时间不太可能影响您的应用程序;两者都很快
就个人而言,在C#中,我更喜欢:

get=>x??(x=val);
我会加上一个时间。。。(编辑:即
Foo3
/
Bar3
,它看起来是
Foo2
/
Foo3
的一个边际改进)

注意:我删除了实际的
列表
创建以避免开销-它现在分配给一个静态列表

代码:

使用BenchmarkDotNet.Attributes;
使用BenchmarkDotNet.Configs;
使用BenchmarkDotNet.Running;
使用System.Collections.Generic;
使用System.Linq;
公共静态类程序
{
静态void Main()=>BenchmarkRunner.Run();
}
[ClrJob,CoreJob]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByParams)]
公共类MyTest
{
[参数(假、真)]
公共布尔是空的{get;set;}
const int operations perinvoke=10000;
private readonly Blab[]blabs=Enumerable.Range(0,OperationsPerInvoke)。选择(XmlExporterAttribute=>new Blab()).ToArray();
[迭代设置]
公共无效重置()
{
如果(我是空的)
{
foreach(blabs中的var blab)blab.Reset();
}
}
[基准(OperationsPerInvoke=OperationsPerInvoke)]
公共图书馆
{
对于(int i=0;i| Method |  Job | Runtime | IsEmpty |     Mean |     Error |    StdDev |   Median |
|------- |----- |-------- |-------- |---------:|----------:|----------:|---------:|
|    Foo |  Clr |     Clr |   False | 1.764 ns | 0.0106 ns | 0.0094 ns | 1.760 ns |
|   Foo2 |  Clr |     Clr |   False | 1.175 ns | 0.0235 ns | 0.0305 ns | 1.185 ns |
|   Foo3 |  Clr |     Clr |   False | 1.165 ns | 0.0227 ns | 0.0347 ns | 1.180 ns |
|    Bar |  Clr |     Clr |   False | 1.957 ns | 0.0350 ns | 0.0293 ns | 1.940 ns |
|   Bar2 |  Clr |     Clr |   False | 1.197 ns | 0.0313 ns | 0.0348 ns | 1.190 ns |
|   Bar3 |  Clr |     Clr |   False | 1.165 ns | 0.0156 ns | 0.0146 ns | 1.170 ns |
|    Foo | Core |    Core |   False | 2.142 ns | 0.0237 ns | 0.0185 ns | 2.135 ns |
|   Foo2 | Core |    Core |   False | 1.172 ns | 0.0232 ns | 0.0524 ns | 1.170 ns |
|   Foo3 | Core |    Core |   False | 1.168 ns | 0.0221 ns | 0.0237 ns | 1.170 ns |
|    Bar | Core |    Core |   False | 2.063 ns | 0.0414 ns | 0.0580 ns | 2.040 ns |
|   Bar2 | Core |    Core |   False | 1.169 ns | 0.0235 ns | 0.0392 ns | 1.170 ns |
|   Bar3 | Core |    Core |   False | 1.151 ns | 0.0230 ns | 0.0379 ns | 1.150 ns |
|        |      |         |         |          |           |           |          |
|    Foo |  Clr |     Clr |    True | 1.767 ns | 0.0174 ns | 0.0154 ns | 1.760 ns |
|   Foo2 |  Clr |     Clr |    True | 1.791 ns | 0.0150 ns | 0.0141 ns | 1.790 ns |
|   Foo3 |  Clr |     Clr |    True | 1.784 ns | 0.0196 ns | 0.0174 ns | 1.780 ns |
|    Bar |  Clr |     Clr |    True | 1.767 ns | 0.0075 ns | 0.0063 ns | 1.770 ns |
|   Bar2 |  Clr |     Clr |    True | 1.784 ns | 0.0086 ns | 0.0067 ns | 1.780 ns |
|   Bar3 |  Clr |     Clr |    True | 1.775 ns | 0.0211 ns | 0.0176 ns | 1.780 ns |
|    Foo | Core |    Core |    True | 2.360 ns | 0.0650 ns | 0.1400 ns | 2.290 ns |
|   Foo2 | Core |    Core |    True | 2.553 ns | 0.0987 ns | 0.1754 ns | 2.450 ns |
|   Foo3 | Core |    Core |    True | 2.464 ns | 0.0649 ns | 0.1894 ns | 2.345 ns |
|    Bar | Core |    Core |    True | 1.697 ns | 0.0234 ns | 0.0183 ns | 1.690 ns |
|   Bar2 | Core |    Core |    True | 1.717 ns | 0.0349 ns | 0.0621 ns | 1.695 ns |
|   Bar3 | Core |    Core |    True | 1.647 ns | 0.0223 ns | 0.0198 ns | 1.640 ns |