.NET对象的创建,什么快?对象、NET

2023-09-04 01:19:07 作者:@倍儿坚强

时的那些有2种方式创建对象?

IS there a difference between those 2 ways of object creation?

new MyClass() { Id = 1, Code = "Test" };

MyClass c = new MyClass();
c.Id = 1;
c.Code = "Test";

什么是快?我假设有2个没有什么区别。

What's faster? I am assuming there is no difference between the 2.

推荐答案

第二个将可能是的几乎可以肯定不明显的速度更快,因为这里涉及到少一个任务,在逻辑。在第一种情况下,code其实就相当于:

The second will possibly be almost certainly insignificantly faster, because there's one fewer assignment involved, logically. In the first case, the code is actually equivalent to:

MyClass tmp = new MyClass()
tmp.Id = 1;
tmp.Code = "Test";
MyClass c = tmp;

这是非常可能的,因为你宣布JIT编译器将这些的Elid一个的新的变量 - 这将不能够这样做,如果你是用一个对象初始化分配到一个现有的变量

It's very possible that the JIT compiler will elide these as you're declaring a new variable - it wouldn't be able to do so if you were assigning to an existing variable with an object initializer.

编辑:我只是试图编译使用和不使用优化开启,而在这个新变量情况下,C#编译器elides两人的如果的它的优化。它不以其他方式(而JIT仍然可以)。在重新分配情况下,它可以使一个可观察的区别,所以我不希望同样的优化。我没有,虽然检查。

I've just tried compiling with and without optimizations turned on, and in this "new variable" case the C# compiler elides the two if it's optimizing. It doesn't otherwise (but the JIT still could). In the "reassignment" case it could make an observable difference, so I wouldn't expect the same optimization. I haven't checked though.

我会很惊讶地看到一种情况,它实际上做了一个显著差异的,所以我会用更具可读性选项,IMO是第一次去。

I would be very surprised to see a situation where it actually made a significant difference though, so I'd go with the more readable option, which IMO is the first.

编辑:我想人们可能会感兴趣的基准显示它发挥作用。这是故意可怕code键使慢隐藏的额外任务 - 我已经创建了一个大的,可变的结构。 Urgh。反正...

I thought folks might be interested in a benchmark showing it making a difference. This is deliberately horrible code to make the hidden extra assignment slow - I've created a big, mutable struct. Urgh. Anyway...

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;
    }
}

结果(有/ O + /调试 - ):

Results (with /o+ /debug-):

NewVariableObjectInitializer: 3328ms
ExistingVariableObjectInitializer: 3300ms
NewVariableDirectSetting: 1464ms
ExistingVariableDirectSetting: 1491ms

我有点惊讶的是,NewVariableObjectInitializer版本比直接设置那些慢......它看起来像C#编译器不会在它为引用类型的方式来优化这种情况。我怀疑是围绕价值类型的一些细微之处是prevents吧。

I'm somewhat surprised that the NewVariableObjectInitializer version is slower than the direct setting ones... it looks like the C# compiler doesn't optimize this case in the way that it does for reference types. I suspect there's some subtlety around value types that prevents it.