Object initializer performance

后端 未结 7 1931
遇见更好的自我
遇见更好的自我 2021-01-04 01:47

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

Is this faster

Object object = new Object
{
    id = 1;
}

than th

相关标签:
7条回答
  • 2021-01-04 02:05

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

    0 讨论(0)
  • 2021-01-04 02:05

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

    0 讨论(0)
  • 2021-01-04 02:21

    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 );
    
    0 讨论(0)
  • 2021-01-04 02:22

    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.

    0 讨论(0)
  • 2021-01-04 02:25

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

    0 讨论(0)
  • 2021-01-04 02:27

    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.

    0 讨论(0)
提交回复
热议问题