基于构造函数的对象初始化

本文关键字:对象 初始化 构造函数 | 更新日期: 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节,其中以"不可见且不可访问的临时变量"的形式显式指定