16

Is the object initializer in c# 3.0 faster then the regular way?

Is this faster

Object object = new Object
{
    id = 1;
}

than this ?

Object object = new Object()

object.id = 1;
user137348
  • 10,166
  • 18
  • 69
  • 89

7 Answers7

24

In Release mode, they will compile to the exact same IL code (assuming that you're actually using a type with an id property instead of Object)

Therefore, there will by definition be no performance difference.

I don't know which one will compile faster, but it would be a minute difference in compilation time and you probably don't care.

However, the object initializer syntax is written faster (less typing), so you should probably use it.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Although they won't actually compile to the *exact* same IL code, the difference is negligible so it doesn't actually matter. – Lasse V. Karlsen Oct 02 '09 at 15:12
  • Only in debug mode; in release mode, it is the same. – SLaks Oct 02 '09 at 15:33
  • 1
    One thing to take care before jumping on the initialize wagon, when exception occurs in initializer or error is logged, the stack trace shows the line of the object creation (aka new ClassName) not line of the property set. – florin Oct 19 '17 at 09:23
10

Ok, from the comment by [SLaks][2], and testing myself after reading it, it turns out the difference I describe here is only present in debug mode. If you compile for release, they all compile to the same code. Learn something new every day :)


(so rest of answer assumes debug mode.)

There is a difference in the IL produced, contrary to what others here have answered, but the difference is negligible, and shouldn't actually have any performance impact on your program at all.

The difference is that using an object initializer, like this:

Object object = new Object
{
    id = 1;
}

The code is actually compiled as though you had written this:

Object temp = new Object();
temp.id = 1;
Object object = temp;

(of course, barring the fact that Object doesn't have an Id field/property, and you can't actually name a variable "object" without using the verbatim identifier syntax "@object".)

Why would this matter? Well, one difference you could possibly notice is that if any of the assignments threw an exception (either writing the value into the object, or obtaining the value from an expression or function throws an exception), then with the object initializer, you won't actually see any object in the variable, whereas in your "manual" code, the object will be there, initialized right up to the point where the exception occured.

A minor difference, which shouldn't have much of an performance difference, but might change the behavior of your program.

This can be verified by looking at the IL. Take this C# program:

using System;

namespace ConsoleApplication3
{
    class Test
    {
        public Int32 Id { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            M1();
            M2();
        }

        static void M1()
        {
            Test t = new Test();
            t.Id = 1;
        }

        static void M2()
        {
            Test t = new Test { Id = 1 };
        }

        static void M3()
        {
            Test t;
            Test temp = new Test();
            temp.Id = 1;
            t = temp;
        }
    }
}

and compile it, run it through Reflector and you'll get this for M1, M2 and 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 
}

If you look at the code, the only thing that differs between M2 and M3 is the name of the second local (<>g__initLocal0 vs temp).

But as others have already answered, the difference won't make any performance difference you should notice.

Binkan Salaryman
  • 3,008
  • 1
  • 17
  • 29
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • I believe that's only true in debug mode; try recompiling in Release (I'm too lazy) – SLaks Oct 02 '09 at 15:22
  • Hah, you're right, learn something new every day, will edit my answer. – Lasse V. Karlsen Oct 02 '09 at 15:24
  • Are we sure this gets compiled out in release mode? This [question here](http://stackoverflow.com/q/1679780/314291) seems to indicate that the `g__initLocalxx` temporary object reference is retained in release mode as well? – StuartLC Feb 26 '14 at 13:14
2

If there are any performance differences (which I doubt there are any), they're negligible. Optimize only where profiler told you to do so.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
2

AFAIK it's just syntactic sugar - the IL produced will be the same

Gordon Mackie JoanMiro
  • 3,499
  • 3
  • 34
  • 42
1

No, it's the same thing.

Joren
  • 14,472
  • 3
  • 50
  • 54
1

It may be faster to type, but it compiles to the same code so there is no runtime benefit.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
1

I've not benchmarked it, but I'd be supprised if they didn't compile to the same thing.

That said, It's easier for me to type when I need something like

var bob = service.GetSingle( new Constraint { UserName = "Bob" } );

I strongly dislike the repeated assignments of properties like

var c = new Constraint();
c.UserName = "Bob";
c.Position = Positions.Manager;
var bob = service.GetSingle( c );
Ball
  • 2,591
  • 3
  • 19
  • 26