【问题标题】:Performance of C# Inline StatementC#内联语句的性能
【发布时间】:2016-01-28 07:20:11
【问题描述】:

我有一个模型的集合

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());

现在考虑通用的实现方式

方法 #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) 个执行。所以,我需要澄清在复杂数据结构中哪一种是最好的方法。

【问题讨论】:

  • 这不是引用类型的工作方式。在第二种方法中,您将拥有一个包含 3 个对单个项目的引用的列表 (Name="", Catagory="Ultra Smart Phone", Year="2016")
  • 请注意,如果您定期使用名称、类别和年份进行初始化,则值得创建一个构造函数。 (另外,你确定这些都应该是字符串吗?你什么时候想要一个不是int 的年份?名称实际上总是一个数字吗?也许类别应该是一个枚举?)
  • @M.kazemAkhgary - 抱歉,我更新了第二种方法。现在帮助我哪一个更可取?
  • @MatthewWatson - 或多或少你是对的。在第一种方法中,只有一个执行应该执行,但在第二种方法中,应该执行超过 25 (>25) 个执行。所以,我需要澄清在复杂数据结构中哪一种是最好的方法。

标签: c# inline observablecollection


【解决方案1】:

新的语法对象初始化器基本上只是一种被翻译成长格式的速记格式。如果您愿意,可以使用某种反汇编程序来确认这一点。你会发现除了一些编译器优化之外,代码几乎是一样的。

例如,这段代码:

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)中。开启优化后,这种差异就会消失。

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

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

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

int[] a2 = new int[3];
a2[0] = 1;
a2[1] = 2;
a2[2] = 3;

【讨论】:

    【解决方案2】:

    第二个不是“comman 方式”(这是我以前从未听说过的术语)。它是:

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

    这就是你学习它的原因。旧语法。没有显着的(尤其是无法衡量的)性能差异。

    【讨论】:

    • 谢谢,你更喜欢哪一个?
    • 轻微更正:更改不在 .NET 中,而是在 C# 3 (v3) 中。对象和集合初始化程序不需要框架支持 - 例如,您可以在面向 .NET 2 时使用它们。 (如果您仍然可以轻松定位 .NET 1,我希望它们也能在那里工作......)
    • 是的,字节码没有区别。但是可能仍然有很多课程没有新语法,而且很多人只是在谷歌上搜索并且从未正确学习过这门语言。
    • 当然——我只是说你应该把它叫做它是什么,一种语言变化。重复 ieaglle 的评论也是值得的 - 由于只创建了一个 MobileModelInfo 的实例,第二个代码目前已被破坏。
    • @JonSkeet - 抱歉,我更新了第二种方法。现在帮助我哪一个更可取?
    猜你喜欢
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2022-07-07
    相关资源
    最近更新 更多