Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any downsides to using an empty object initializer?

Tags:

c#

.net

I'm doing a code review and found a line where one of our developers is creating an object using an empty object initializer like this:

List<Floorplan> floorplans = new List<Floorplan> { };

I don't know why he would instantiate this way rather than:

List<Floorplan> floorplans = new List<Floorplan>();

Are there any downsides to object instantiation using empty object initializers? Other than being stylistically inconsistent I want to know if there is a reason avoid this approach. Something tells me this smells but I want to be sure before I say anything.

like image 900
Jeff Avatar asked Aug 02 '13 17:08

Jeff


People also ask

What is object initialization why it is required?

In object initializer, you can initialize the value to the fields or properties of a class at the time of creating an object without calling a constructor. In this syntax, you can create an object and then this syntax initializes the freshly created object with its properties, to the variable in the assignment.

Why do we initialize objects in C#?

Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements.

What is object initializer?

An object initializer is an expression that describes the initialization of an Object . Objects consist of properties, which are used to describe an object. The values of object properties can either contain primitive data types or other objects.

What is the difference between initializer and constructor?

Constructor is a special non-static member function of a class that is used to initialize objects of its class type. In the definition of a constructor of a class, member initializer list specifies the initializers for direct and virtual bases and non-static data members.


2 Answers

The compiled result is the same.

The following C#:

static void Main()
{
    var x = new List<int>();
    var y = new List<int> { };
}

Compiles into the following IL:

.method private hidebysig static 
    void Main () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 14 (0xe)
    .maxstack 1
    .entrypoint
    .locals init (
        [0] class [mscorlib]System.Collections.Generic.List`1<int32> x,
        [1] class [mscorlib]System.Collections.Generic.List`1<int32> y
    )

    IL_0000: nop
    IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
    IL_0006: stloc.0
    IL_0007: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
    IL_000c: stloc.1
    IL_000d: ret
} // end of method Program::Main

If you add a value to the collections:

static void Main()
{
    var x = new List<int>();
    x.Add(1);
    var y = new List<int> { 1 };
}

This is the resulting IL:

.method private hidebysig static 
    void Main () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 32 (0x20)
    .maxstack 2
    .entrypoint
    .locals init (
        [0] class [mscorlib]System.Collections.Generic.List`1<int32> x,
        [1] class [mscorlib]System.Collections.Generic.List`1<int32> y,
        [2] class [mscorlib]System.Collections.Generic.List`1<int32> '<>g__initLocal0'
    )

    IL_0000: nop
    IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: ldc.i4.1
    IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
    IL_000e: nop
    IL_000f: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
    IL_0014: stloc.2
    IL_0015: ldloc.2
    IL_0016: ldc.i4.1
    IL_0017: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
    IL_001c: nop
    IL_001d: ldloc.2
    IL_001e: stloc.1
    IL_001f: ret
} // end of method Program::Main

This shows how collection initializers are only syntax sugar. Because collection initializers were not originally part of C#, I think people are more used to the constructor syntax. If I came across some code that used an empty collection initializer, I would wonder to myself why, but it certainly doesn't have any severe readability issues. If one is intelligent enough to understand code at all, then {} vs () shouldn't be so upsetting that it undermines one's ability to comprehend what the code is doing. It comes down to a matter of opinion. Do what your team agrees on, and if it's just you, then use it to your hearts content.

like image 132
Dan Avatar answered Sep 25 '22 22:09

Dan


There are no downsides but favor readability in this case. If you don't need the extra brackets while instantiating then don't use them plain and simple.

I would even go as far as saying favor productivity. A lot of the answers here are going deeper in trying to answer this question. Even if one technique was better than the other we're talking about what's really a micro optimization.

like image 26
Ralph Caraveo Avatar answered Sep 25 '22 22:09

Ralph Caraveo