Setting properties via object initialization or not : Any difference ?
Asked Answered
L

5

38

Here's a simple question : Is there any (performance) difference between this :

Person person = new Person()
{
  Name = "Philippe",
  Mail = "[email protected]",
};

and this

Person person = new Person();
person.Name = "Philippe";
person.Mail = "[email protected]";

You can imagine bigger object with more properties.

Leyes answered 11/2, 2011 at 20:1 Comment(1)
Also worth checking out this answer to a similar question.Heyes
J
44

They are almost exactly equivalent except that the first method (using an object initializer) only works in C# 3.0 and newer. Any performance difference is only minor and not worth worrying about.

They produce almost identical IL code. The first gives this:

.method private hidebysig instance void ObjectInitializer() cil managed
{
    .maxstack 2
    .locals init (
        [0] class Person person,
        [1] class Person <>g__initLocal0)
    L_0000: newobj instance void Person::.ctor()
    L_0005: stloc.1 
    L_0006: ldloc.1 
    L_0007: ldstr "Philippe"
    L_000c: callvirt instance void Person::set_Name(string)
    L_0011: ldloc.1 
    L_0012: ldstr "[email protected]"
    L_0017: callvirt instance void Person::set_Mail(string)
    L_001c: ldloc.1 
    L_001d: stloc.0 
    L_001e: ldloc.0 
    L_001f: callvirt instance string [mscorlib]System.Object::ToString()
    L_0024: pop 
    L_0025: ret 
}

The second gives this:

.method private hidebysig instance void SetProperties() cil managed
{
    .maxstack 2
    .locals init (
        [0] class Person person)
    L_0000: newobj instance void Person::.ctor()
    L_0005: stloc.0 
    L_0006: ldloc.0 
    L_0007: ldstr "Philippe"
    L_000c: callvirt instance void Person::set_Name(string)
    L_0011: ldloc.0 
    L_0012: ldstr "[email protected]"
    L_0017: callvirt instance void Person::set_Mail(string)
    L_001c: ldloc.0 
    L_001d: callvirt instance string [mscorlib]System.Object::ToString()
    L_0022: pop 
    L_0023: ret 
}

As you can see, nearly identical code is generated. See below for the exact C# code I compiled.

Performance measurements show very similar results with a very small performance improvement for using the object initializer syntax:

Method               Iterations per second
ObjectInitializer    8.8 million
SetProperties        8.6 million

Code I used for testing the performance:

using System;

class Person
{
    public string Name { get; set; }
    public string Mail { get; set; }
}

class Program
{
    private void ObjectInitializer()
    {
        Person person = new Person()
        {
            Name = "Philippe",
            Mail = "[email protected]",
        };
        person.ToString();
    }

    private void SetProperties()
    {
        Person person = new Person();
        person.Name = "Philippe";
        person.Mail = "[email protected]";
        person.ToString();
    }

    private const int repetitions = 100000000;

    private void Time(Action action)
    {
        DateTime start = DateTime.UtcNow;
        for (int i = 0; i < repetitions; ++i)
        {
            action();
        }
        DateTime end = DateTime.UtcNow;
        Console.WriteLine(repetitions / (end - start).TotalSeconds);
    }

    private void Run()
    {
        Time(ObjectInitializer);
        Time(SetProperties);
        Console.WriteLine("Finished");
        Console.ReadLine();
    }

    private static void Main()
    {
        new Program().Run();
    }
}
Jonejonell answered 11/2, 2011 at 20:3 Comment(3)
Well, as long as you have the 3.0 compiler, you can use it in code written for .net 2.0.Popish
So it's note heavier to do it with object initializer. It's there a preferred way ?Leyes
Personal opinion: For simple objects or initialized with just static values, like this example, initializer block is ok - clean to read. If I have to assign a lot of properties or use variables I tend to use standard assignment option. Simply because if it fails for whatever reason (null object etc) inside OI block, it's harder to figure out where it's failing. Where with standard assignment it will tell you exactly where the problem is.Curettage
M
10

One additional thing worth noting is this:

If you fail to handle an exception in your constructor, you'll get a TypeInitializationException. While that may not seem so bad, the truth is that it conceals the real cause of the problem, and makes it harder to track down.

If, on the other hand, you use an object initializer, you're invoking each property individually outside of the constructor, and any thrown exceptions will be very clear and very evident: they won't be masked by the TypeInitializationException.

In general, it's a bad idea to throw exceptions in a constructor. If you want to avoid that scenario, go with the initializer.

Mauk answered 11/2, 2011 at 21:13 Comment(1)
+1 for making me realise object initialization only happens AFTER the constructor had run.Merissa
M
1

As others have said, no, there is no difference. Note that the first example isn't actually using a constructor for those arguments. It's using the "object initializer" language feature introduced in C# 3.0. The constructor being called is the default parameterless constructor just like the second example.

The two examples actually compile down to (nearly) the same IL code and for all intents and purposes do the same thing. The first example is just a relatively newer syntax to accomplish the task <opinion>in an easier and more expressive way</opinion>.

Metaphysical answered 11/2, 2011 at 20:11 Comment(0)
B
0

No. The first way is new in .NET 3.5 but the second example is for previous versions of C#.

Bunni answered 11/2, 2011 at 20:4 Comment(0)
S
0

Performance-wise there is no significant difference, as other replies have shown.

However, creating an object using an initializer with 2 parameters seems to me like you state your intent to anyone who is using it, forming a "contract" saying: "these 2 parameters are the minimum for the functionality of the class" (although the correct way to express that intent would be to use a constructor).

I tend to think of the initializer syntax this way, although it's more or less just syntactic sugar. I use a mix of both syntaxes in my code. But then again, that's my personal style.

Saddlecloth answered 9/8, 2015 at 10:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.