.net 对象初始值设定项性能

.net 对象初始值设定项性能,.net,c#-3.0,.net,C# 3.0,c#3.0中的对象初始值设定项是否比常规方法快 这个快一点吗 Object object = new Object { id = 1; } 比这个好 Object object = new Object() object.id = 1; 不,这是一样的。在发布模式下,它们将编译为完全相同的IL代码(假设您实际使用的类型具有id属性,而不是对象) 因此,根据定义,不会有性能差异 我不知道哪一个会编译得更快,但编译时间会有细微差别,你可能不在乎 但是,对象初始值设定项语法的编写速度更快

c#3.0中的对象初始值设定项是否比常规方法快

这个快一点吗

Object object = new Object
{
    id = 1;
}
比这个好

Object object = new Object()

object.id = 1;

不,这是一样的。

在发布模式下,它们将编译为完全相同的IL代码(假设您实际使用的类型具有
id
属性,而不是
对象

因此,根据定义,不会有性能差异

我不知道哪一个会编译得更快,但编译时间会有细微差别,你可能不在乎


但是,对象初始值设定项语法的编写速度更快(键入更少),因此您可能应该使用它。

它的键入速度可能更快,但它编译为相同的代码,因此在运行时没有任何好处。

如果有任何性能差异(我怀疑有任何差异),它们可以忽略不计。仅在profiler告诉您的地方进行优化。

我还没有对其进行基准测试,但如果它们没有编译成相同的东西,我会感到非常满意

也就是说,当我需要这样的东西时,打字对我来说更容易

var bob = service.GetSingle( new Constraint { UserName = "Bob" } );
我非常不喜欢像这样的属性的重复赋值

var c = new Constraint();
c.UserName = "Bob";
c.Position = Positions.Manager;
var bob = service.GetSingle( c );

好吧,这只是语法上的糖分——从[SLaks][2]的评论来看,生成的IL将是相同的

好的,并且在阅读后对自己进行了测试,结果证明我在这里描述的差异仅在调试模式下存在。如果您编译为发行版,它们都编译为相同的代码。每天学习新东西:)


(所以答案的其余部分采用调试模式。)

产生的IL与其他人的回答不同,但差异可以忽略不计,实际上不应该对程序的性能产生任何影响

区别在于使用对象初始值设定项,如下所示:

Object object = new Object
{
    id = 1;
}
代码实际上是编译的,就像您编写的:

Object temp = new Object();
temp.id = 1;
Object object = temp;
(当然,除非对象没有Id字段/属性,而且如果不使用逐字标识符语法“@Object”,就不能实际命名变量“Object”。)

这有什么关系?您可能注意到的一个区别是,如果任何赋值引发异常(将值写入对象,或从表达式或函数获取值引发异常),那么使用对象初始值设定项,您实际上不会在变量中看到任何对象,而在“手动”代码中,对象将在那里,初始化到异常发生的位置

一个微小的差异,它不应该有太大的性能差异,但可能会改变程序的行为

这可以通过查看IL来验证。以这个C#程序为例:

编译它,运行它,你会得到M1,M2和M3的结果:

.method private hidebysig static void M1() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ret 
}

.method private hidebysig static void M2() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t,
        [1] class ConsoleApplication3.Test <>g__initLocal0)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ldloc.1 
    L_0010: stloc.0 
    L_0011: ret 
}

 .method private hidebysig static void M3() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t,
        [1] class ConsoleApplication3.Test temp)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ldloc.1 
    L_0010: stloc.0 
    L_0011: ret 
}
.method private hidebysing static void M1()cil managed
{
.maxstack 2
.init(
[0]类控制台应用程序3.测试(t)
L_0000:没有
L_0001:newobj实例无效控制台应用程序3.Test::.ctor()
L_0006:stloc.0
L_0007:ldloc.0
L_0008:ldc.i4.1
L_0009:callvirt实例void控制台应用程序3.Test::set_Id(int32)
L_000e:没有
L_000f:ret
}
.method private隐藏静态void M2()cil managed
{
.maxstack 2
.init(
[0]类控制台应用程序3.测试t,
[1] 类ConsoleApplication3.Test g_uuinitlocal0)
L_0000:没有
L_0001:newobj实例无效控制台应用程序3.Test::.ctor()
L_0006:stloc.1
L_0007:ldloc.1
L_0008:ldc.i4.1
L_0009:callvirt实例void控制台应用程序3.Test::set_Id(int32)
L_000e:没有
L_000f:ldloc.1
L_0010:stloc.0
L_0011:ret
}
.method private隐藏静态void M3()cil managed
{
.maxstack 2
.init(
[0]类控制台应用程序3.测试t,
[1] 类控制台应用程序3.测试温度)
L_0000:没有
L_0001:newobj实例无效控制台应用程序3.Test::.ctor()
L_0006:stloc.1
L_0007:ldloc.1
L_0008:ldc.i4.1
L_0009:callvirt实例void控制台应用程序3.Test::set_Id(int32)
L_000e:没有
L_000f:ldloc.1
L_0010:stloc.0
L_0011:ret
}
如果查看代码,M2和M3之间唯一不同的是第二个本地名(
g_uuinitlocal0
vs
temp


但是,正如其他人已经回答的那样,这种差异不会对性能产生任何影响,您应该注意到。

尽管他们实际上不会编译为完全相同的IL代码,但这种差异可以忽略不计,因此实际上并不重要。仅在调试模式下;在发布模式下,情况也是如此。在开始初始化之前,需要注意的一点是,当初始化程序中出现异常或记录错误时,堆栈跟踪显示的是对象创建的行(也称为新类名),而不是属性集的行。我相信只有在调试模式下才是这样;尝试在发行版中重新编译(我太懒了)哈,你是对的,每天学习一些新的东西,将编辑我的答案。我们确定这会在发行版中编译出来吗?这似乎表明
g_uuinitlocalxx
临时对象引用也保留在发布模式中?
.method private hidebysig static void M1() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ret 
}

.method private hidebysig static void M2() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t,
        [1] class ConsoleApplication3.Test <>g__initLocal0)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ldloc.1 
    L_0010: stloc.0 
    L_0011: ret 
}

 .method private hidebysig static void M3() cil managed
{
    .maxstack 2
    .locals init (
        [0] class ConsoleApplication3.Test t,
        [1] class ConsoleApplication3.Test temp)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.1 
    L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
    L_000e: nop 
    L_000f: ldloc.1 
    L_0010: stloc.0 
    L_0011: ret 
}