基于构造函数的对象初始化
本文关键字:对象 初始化 构造函数 | 更新日期: 2023-09-27 18:12:17
像这样构造和分配类的属性之间是否存在显著的性能差异(在运行时和/或编译时):
Employee currentUser = new Employee();
currentUser.Name = "Bob";
或者像这样:
Employee currentUser = new Employee() { Name = "Bob" };
我的实际示例并没有那么简单,类的属性实际上是分配给一些长linq表达式的。
我搜索了谷歌和Stack Overflow的答案,但我只找到了关于最佳实践的问题,什么时候使用任何一种方法,而不是任何与性能相关的问题。
如果我问了一个愚蠢的问题,请提前道歉。No。这只是语法上的错误。生成的IL将是相同的(将使用IL更新)
internal class Foo
{
public string Bar { get; set; }
}
class Program
{
static void Main(string[] args)
{
Foo f = new Foo()
{
Bar = "Baaz"
};
Console.WriteLine("Now the old way sugar");
Foo f2 = new Foo();
f2.Bar = "Baaz";
}
}
现在IL:
IL_0000: nop
IL_0001: newobj instance void SimpleDataPlayGround.Foo::.ctor()
IL_0006: stloc.2
IL_0007: ldloc.2
IL_0008: ldstr "Baaz"
IL_000d: callvirt instance void SimpleDataPlayGround.Foo::set_Bar(string)
IL_0012: nop
IL_0013: ldloc.2
IL_0014: stloc.0
IL_0015: ldstr "Now the old way sugar"
IL_001a: call void [mscorlib]System.Console::WriteLine(string)
IL_001f: nop
IL_0020: newobj instance void SimpleDataPlayGround.Foo::.ctor()
IL_0025: stloc.1
IL_0026: ldloc.1
IL_0027: ldstr "Baaz"
IL_002c: callvirt instance void SimpleDataPlayGround.Foo::set_Bar(string)
IL_0031: nop
IL_0032: ret
<标题> 更新
好的,经过Jon的评论,很明显,有一个细微的差异。至于问题——主要是性能影响——没有,但正如Jon指出的,如果一个对象用于它自己的再创造,这可能是重要的。
标题>这两个并不完全相同。对象初始化式的形式更像是这样的(至少在逻辑上;我相信有一些的情况下,c#编译器将只使用一个变量):
Employee tmp = new Employee();
tmp.Name = "Bob";
Employee currentUser = tmp;
如果要更改变量的值,这一点尤为重要。例如:
Employee currentUser = new Employee { Name = "Bob" };
currentUser = new Employee { Name = currentUser.Name + "Foo" };
这里的结果将是一个名为"BobFoo"的雇员,不是只是"Foo",如果对变量的赋值发生在属性setter之前,则会得到。
这在读取变量当前值的其他情况下可能很重要,例如在属性设置器中。不太可能,但有可能。
详情见第7.6.10.2节,其中以"不可见且不可访问的临时变量"的形式显式指定