C# 内联语句的性能

本文关键字:性能 语句 | 更新日期: 2023-09-27 18:32:24

我有一个模型集合

public class MobileModelInfo
{
    public string Name { get; set; }
    public string Catagory { get; set; }
    public string Year { get; set; }
}

在这里,我通过内联单个执行语句MobileModelInfo分配到ObservableCollection

方法#1

ObservableCollection<MobileModelInfo> mobList = new ObservableCollection<MobileModelInfo>((new List<MobileModelInfo>(){
    new MobileModelInfo { Name = "S4", Catagory = "Smart Phone", Year = "2011" },
    new MobileModelInfo { Name = "S5", Catagory = "Smart Phone", Year = "2013" },
    new MobileModelInfo { Name = "S6", Catagory = "Ultra Smart Phone", Year = "2015" },
    new MobileModelInfo { Name = "", Catagory = "Ultra Smart Phone", Year = "2016" }
}).Where(i => !string.IsNullOrEmpty(i.Name)).ToList());

现在考虑 Comman 的实现方式

方法#2

ObservableCollection<MobileModelInfo> mobList = new ObservableCollection<MobileModelInfo>();
MobileModelInfo mobObject = new MobileModelInfo();
mobObject.Name = "S4";
mobObject.Catagory = "Smart Phone";
mobObject.Year = "2011";
if(!string.IsNullOrEmpty(mobObject.Name))
    mobList.Add(mobObject);
mobObject = new MobileModelInfo();
mobObject.Name = "S5";
mobObject.Catagory = "Smart Phone";
mobObject.Year = "2013";
if(!string.IsNullOrEmpty(mobObject.Name))
    mobList.Add(mobObject);
mobObject = new MobileModelInfo();
mobObject.Name = "S6";
mobObject.Catagory = "Ultra Smart Phone";
mobObject.Year = "2015";
if(!string.IsNullOrEmpty(mobObject.Name))
    mobList.Add(mobObject);
mobObject = new MobileModelInfo();
mobObject.Name = "";
mobObject.Catagory = "Ultra Smart Phone";
mobObject.Year = "2016";
if(!string.IsNullOrEmpty(mobObject.Name))
    mobList.Add(mobObject);

在这两种方法中,哪一种性能好?在我的主项目中,我有一个非常复杂的模型类集合。所以,请协助我选择最好的方式...

在第一种方法中,只有一个执行应该执行,因为它将由编译器扩展,但在第二种方法中,应该执行超过 25 (>25) 个执行。因此,我需要澄清复杂数据结构中哪一种是最佳方法。

C# 内联语句的性能

新的语法对象初始值设定项基本上只是一种转换为长格式的速记格式。 如果您愿意,您可以使用某种反汇编器来确认这一点。 您会发现代码尽可能接近相同,除非进行一些编译器优化。

例如,此代码:

TestClass t1 = new TestClass { iVal = 1, sVal = "two" };

生成以下 IL(根据 LINQPad):

IL_0001:  newobj      UserQuery+TestClass..ctor
IL_0006:  stloc.2     
IL_0007:  ldloc.2     
IL_0008:  ldc.i4.1    
IL_0009:  stfld       UserQuery+TestClass.iVal
IL_000E:  ldloc.2     
IL_000F:  ldstr       "two"
IL_0014:  stfld       UserQuery+TestClass.sVal
IL_0019:  ldloc.2     
IL_001A:  stloc.0     // t1

这是另一种方式:

TestClass t2 = new TestClass();
t2.iVal = 1;
t2.sVal = "two";

及其 IL:

IL_001B:  newobj      UserQuery+TestClass..ctor
IL_0020:  stloc.1     // t2
IL_0021:  ldloc.1     // t2
IL_0022:  ldc.i4.1    
IL_0023:  stfld       UserQuery+TestClass.iVal
IL_0028:  ldloc.1     // t2
IL_0029:  ldstr       "two"
IL_002E:  stfld       UserQuery+TestClass.sVal

这里唯一的区别是,首先创建一个临时变量(loc.2)来完成创建,然后将其存储在命名的局部变量(loc.0 中)。 当您启用优化时,这种差异会消失。

因此,您可以使用任一方法,性能差异几乎为零。 就个人而言,我更喜欢新的对象初始值设定项形式,就像我更喜欢 LINQ 查询语法一样。 两者都只是后台发生的事情的语法糖,但它们在阅读代码的方式和编写方式上可能会有很大的差异。

顺便说一下,数组初始值设定项完全相同。 这两者生成几乎相同的代码:

int[] a1 = new int[] { 1, 2, 3 };
int[] a2 = new int[3];
a2[0] = 1;
a2[1] = 2;
a2[2] = 3;

第二个不是"Comman Way"(这是我以前从未听说过的术语)。是的:

  • 复杂(设置后检查名称属性是否为 null。
  • 某个古老的 .NET 更新启用新语法之前执行此操作的唯一方法。

这几乎就是你学习它的原因。旧语法。没有显著的 - 特别是没有可衡量的 - 性能差异。