Performance of Constructors versus Object Initialization in C#

If you work in C#, you might see several different ways of constructing a new object around your codebase – constructors and general object initialization.

Constructor:
var t = new Obj(var1, var2, …)
Object initialization:
var t = new Obj() {
Var1 = var1,
Var2 = var2,
  …
}
(Or maybe a mix of both)
At my work, I primarily see object initialization used. I continued the practice because, well, it was the style of the code. However, I was curious as to how big the performance impact of object initialization was (it’s going to be slower because it creates the object first with default values), so I created a little test program and checked out the generated assembly.
class Program
{
    static void Main(string[] args)
    {
        TestClass var1 = new TestClass(“hi”, “hello”, “sup”);
        TestClass var2 = new TestClass()
        {
            Data1 = “hi”,
            Data2 = “hello”,
            Data3 = “sup”
        };
    }
}
public class TestClass
{
    public TestClass()
    {
    }
    public TestClass(string data1, string data2, string data3)
    {
        Data1 = data1;
        Data2 = data2;
        Data3 = data3;
    }
    public string Data1 { get; set; }
    public string Data2 { get; set; }
    public string Data3 { get; set; }
}
You can view the assembly by starting the program, pause the program, and go to Debug->Windows->Disassembly.
Here’s the assembly for the constructor case:
TestClass var1 = new TestClass(“hi”, “hello”, “sup”);
01252DC5  mov         ecx,57E0FB0h
01252DCA  call        00EE30F4
01252DCF  mov         dword ptr [ebp-48h],eax
01252DD2  push        dword ptr ds:[3BA2330h]
01252DD8  push        dword ptr ds:[3BA2334h]
01252DDE  mov         edx,dword ptr ds:[3BA232Ch]
01252DE4  mov         ecx,dword ptr [ebp-48h]
01252DE7  call        01250D00
01252DEC  mov         eax,dword ptr [ebp-48h]
01252DEF  mov         dword ptr [ebp-40h],eax
EAX-EDX are just general data registers. We call our constructor, push the parameters onto the stack, and then move the data into the right place. Simple and clean.
However, here’s the code for the object initialization version:
TestClass var2 = new TestClass()
{
Data1 = “hi”,
Data2 = “hello”,
Data3 = “sup”
};
01252DF2  mov         ecx,57E0FB0h
01252DF7  call        00EE30F4
01252DFC  mov         dword ptr [ebp-4Ch],eax
01252DFF  mov         ecx,dword ptr [ebp-4Ch]
01252E02  call        01250CF8
01252E07  mov         edx,dword ptr ds:[3BA232Ch]
01252E0D  mov         ecx,dword ptr [ebp-4Ch]
01252E10  cmp         dword ptr [ecx],ecx
01252E12  call        01250D10
01252E17  nop
01252E18  mov         edx,dword ptr ds:[3BA2330h]
01252E1E  mov         ecx,dword ptr [ebp-4Ch]
01252E21  cmp         dword ptr [ecx],ecx
01252E23  call        01250D20
01252E28  nop
……
Eesh. It generates a lot of extra code just to assign members, including a surprising no-op. Not sure why that’s there, but it was enlightening to see how much more code is generated versus the constructor method.
Now, you’re probably thinking “Well, what’s the harm? Most machines these days can handle a few extra cycles, and my app isn’t fighting for performance!” Well, there’s a few reasons you should use constructors:
  • If you have a pretty complex object, and you’re purely initializing many of them using the second technique, this extra binary space and time is gonna add up.
  • Constructors provide a good way to enforce proper object construction. A good constructor is going to make sure all required data points are entered.
However, there are good reasons to go about with object initialization:
  • Creating a ton of different constructors is tedious and messy. Any time you add a new field, that’s quite a bit more work.
  • It looks cleaner code wise. You can see that member X is assigned value Y, and not have to consult the constructor definition.
I also learned that our code base primarily used object initialization because one of the developers was a pretty heavy JavaScript developer, so it makes sense to keep that style. However, now that I’ve learned this, I’m primarily going to go with constructors from now on.