.NET 对象创建,哪个更快?
这两种对象创建方式有区别吗?
new MyClass() { Id = 1, Code = "Test" };
或者
MyClass c = new MyClass();
c.Id = 1;
c.Code = "Test";
什么更快?我假设2之间没有区别。
IS there a difference between those 2 ways of object creation?
new MyClass() { Id = 1, Code = "Test" };
or
MyClass c = new MyClass();
c.Id = 1;
c.Code = "Test";
What's faster? I am assuming there is no difference between the 2.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
第二个可能几乎肯定会快一点,因为从逻辑上讲,涉及的作业较少。在第一种情况下,代码实际上相当于:
当您声明一个新变量时,JIT编译器很可能会忽略这些 - 如果您是这样,它就无法这样做使用对象初始值设定项分配给现有变量。
编辑:我刚刚尝试过在启用和不启用优化的情况下进行编译,在这种“新变量”情况下,C# 编译器会忽略它正在优化的两个 if 。否则就不会(但 JIT 仍然可以)。在“重新分配”的情况下,它可能会产生明显的差异,所以我不期望有相同的优化。不过我还没有检查过。
我会非常惊讶地看到它实际上产生了显着差异的情况,所以我会选择更具可读性的选项,IMO 是第一个。
编辑:我认为人们可能对显示它产生影响的基准感兴趣。这是故意编写的可怕代码,目的是使隐藏的额外分配变慢 - 我创建了一个大的、可变的结构。呃。无论如何...
结果(使用 /o+ /debug-):
我有点惊讶 NewVariableObjectInitializer 版本比直接设置版本慢...看起来 C# 编译器没有以它的方式优化这种情况对于引用类型。我怀疑值类型有一些微妙之处阻止了它。
The second will possibly be almost certainly insignificantly faster, because there's one fewer assignment involved, logically. In the first case, the code is actually equivalent to:
It's very possible that the JIT compiler will elide these as you're declaring a new variable - it wouldn't be able to do so if you were assigning to an existing variable with an object initializer.
EDIT: I've just tried compiling with and without optimizations turned on, and in this "new variable" case the C# compiler elides the two if it's optimizing. It doesn't otherwise (but the JIT still could). In the "reassignment" case it could make an observable difference, so I wouldn't expect the same optimization. I haven't checked though.
I would be very surprised to see a situation where it actually made a significant difference though, so I'd go with the more readable option, which IMO is the first.
EDIT: I thought folks might be interested in a benchmark showing it making a difference. This is deliberately horrible code to make the hidden extra assignment slow - I've created a big, mutable struct. Urgh. Anyway...
Results (with /o+ /debug-):
I'm somewhat surprised that the NewVariableObjectInitializer version is slower than the direct setting ones... it looks like the C# compiler doesn't optimize this case in the way that it does for reference types. I suspect there's some subtlety around value types that prevents it.
我通过创建 1 亿个对象进行了测试,每个对象都使用参数化构造函数、带初始化程序的无参数构造函数和带 setter 的无参数构造函数,并且根本没有可测量的差异。执行时间略有不同,但以不同的顺序运行测试会改变结果,因此差异只是由于垃圾收集器在不同的时间启动所致。
创建 1 亿个对象大约需要 1.5 秒,因此也没有太多理由尝试让它更快。
就我个人而言,我更喜欢参数化构造函数,因为这样我就可以将属性设置器设置为私有,这样我就可以使类不可变(如果我愿意):
此外,这样您可以确保在创建对象时所有属性都已正确设置。
I tested by creating 100 million objects each using a parameterised constructor, a parameterless constructor with initialiser, and a parameterless constructor with setters, and there is no measurable difference at all. There was a slight difference in execution time, but running the tests in different order changed the results, so the differences are just due to the garbage collector kicking in at different times.
Creating 100 million objects took about 1.5 seconds, so there isn't much reason to try to make it faster either.
Personally I prefer a parameterised constructor, as I then can make the property setters private so that I can make the class immutable if I want to:
Also, this way you can make sure that all properties have been set properly when the object is created.
为了说明 M Skeet 的代码,这里是 IL(注意方法 #1 的附加 ldloc stloc)
To illustrate M Skeet's code, here's the IL (note the additional ldloc stloc for method #1)
他们是一样的。但我们都更喜欢第一个,它更具可读性和更清晰,不是吗?
They are the same. But we all prefer the first one, it's more readable and clearer, isn't it?