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

时间:2011-10-24 08:34:54

标签: c#

在构造和分配类的属性之间是否存在显着的性能差异(在运行时和/或编译时):

Employee currentUser = new Employee();
currentUser.Name = "Bob";

或者像这样:

Employee currentUser = new Employee() { Name = "Bob" };

我的实际例子并不那么简单,类的属性实际上是分配给一些长linq表达式。

我搜索了Google和Stack Overflow的答案,但我只发现了有关最佳做法的问题,何时使用这两种方法,而不是任何与性能相关的问题。

如果我问一个愚蠢的问题,请提前道歉。

2 个答案:

答案 0 :(得分:3)

没有。这只是一种语法糖。生成的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指出之外没有,如果一个对象用于自己的重新创建,这可能很重要。

答案 1 :(得分:3)

两者不是相当相同。对象初始化器形式转换为更像这样的东西(至少在逻辑上;我相信有一些情况,其中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”,如果变量的分配发生在之前,您将获得 em>属性设定者。

这在读取变量的当前值的其他情况下可能很重要,例如在物业设定者。不太可能,但可能。

有关详细信息,请参阅第7.6.10.2节,其中明确指定了“不可见且无法访问的临时变量”。