这两种对象创建方式之间有区别吗?
new MyClass() { Id = 1, Code = "Test" };
Run Code Online (Sandbox Code Playgroud)
要么
MyClass c = new MyClass();
c.Id = 1;
c.Code = "Test";
Run Code Online (Sandbox Code Playgroud)
什么更快?我假设2之间没有区别.
Jon*_*eet 18
第二个可能几乎肯定会更快,因为从逻辑上讲,涉及的任务较少.在第一种情况下,代码实际上等同于:
MyClass tmp = new MyClass()
tmp.Id = 1;
tmp.Code = "Test";
MyClass c = tmp;
Run Code Online (Sandbox Code Playgroud)
当您声明一个新变量时,JIT编译器很可能会忽略它们- 如果您使用对象初始化程序分配给现有变量,它将无法执行此操作.
编辑:我刚刚尝试使用和不使用优化进行编译,在这个"新变量"的情况下,如果它正在优化,C#编译器会忽略这两个.否则它没有(但JIT仍然可以).在"重新分配"的情况下,它可以产生可观察到的差异,因此我不希望进行相同的优化.我没有检查过.
我会非常惊讶地看到它实际上产生了显着差异的情况,所以我选择了更具可读性的选项,IMO是第一个.
编辑:我认为人们可能对基准测试感兴趣,表明它有所作为.这是一个故意可怕的代码,使隐藏的额外任务变慢 - 我已经创建了一个大的,可变的结构.Urgh.无论如何...
using System;
using System.Diagnostics;
struct BigStruct
{
public int value;
#pragma warning disable 0169
decimal a1, a2, a3, a4, a5, a6, a7, a8;
decimal b1, b2, b3, b4, b5, b6, b7, b8;
decimal c1, c2, c3, c4, c5, c6, c7, c8;
decimal d1, d2, d3, d4, d5, d6, d7, d8;
#pragma warning restore 0169
}
class Test
{
const int Iterations = 10000000;
static void Main()
{
Time(NewVariableObjectInitializer);
Time(ExistingVariableObjectInitializer);
Time(NewVariableDirectSetting);
Time(ExistingVariableDirectSetting);
}
static void Time(Func<int> action)
{
Stopwatch stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
Console.WriteLine("{0}: {1}ms",
action.Method.Name,
stopwatch.ElapsedMilliseconds);
}
static int NewVariableObjectInitializer()
{
int total = 0;
for (int i = 0; i < Iterations; i++)
{
BigStruct b = new BigStruct { value = i };
total += b.value;
}
return total;
}
static int ExistingVariableObjectInitializer()
{
int total = 0;
BigStruct b;
for (int i = 0; i < Iterations; i++)
{
b = new BigStruct { value = i };
total += b.value;
}
return total;
}
static int NewVariableDirectSetting()
{
int total = 0;
for (int i = 0; i < Iterations; i++)
{
BigStruct b = new BigStruct();
b.value = i;
total += b.value;
}
return total;
}
static int ExistingVariableDirectSetting()
{
int total = 0;
BigStruct b;
for (int i = 0; i < Iterations; i++)
{
b = new BigStruct();
b.value = i;
total += b.value;
}
return total;
}
}
Run Code Online (Sandbox Code Playgroud)
结果(使用/ o +/debug-):
NewVariableObjectInitializer: 3328ms
ExistingVariableObjectInitializer: 3300ms
NewVariableDirectSetting: 1464ms
ExistingVariableDirectSetting: 1491ms
Run Code Online (Sandbox Code Playgroud)
我有些惊讶于NewVariableObjectInitializer版本比直接设置版本慢......看起来C#编译器没有像它对引用类型那样优化这种情况.我怀疑在价值类型方面有一些微妙的东西会阻止它.