Abdelfattah Radwan
Abdelfattah Radwan

Reputation: 475

What is the difference between a struct constructor with `this()` at the end and another without?

Let's say we have these two structs...

public struct Example
{
    public int Number { get; set; }

    public Example(int Number)
    {
        Number = number;
    }
}

and:

public struct Example
{
    public int Number { get; set; }

    public Example(int number) : this()
    {
        Number = number;
    }
}

You can see that there's a struct with a constructor with **this()** at the end and another without.

What is the difference between the two?

Upvotes: 4

Views: 337

Answers (4)

CSDev
CSDev

Reputation: 3235

Calling this() initializes all fields with zeroes. C# compiler requires all struct fields to be initialized in constructor. So if you want to specify not all fields you should call this().

Will not compile:

struct A
{
    public int field1;
    public string field2;

     public A(string str)
     {
         field2 = str;
     }
}

Gives:

Error CS0171 Field 'A.field1' must be fully assigned before control is returned to the caller ...

Is OK:

struct A
{
    public int field1;
    public string field2;

    public A(string str) : this()
    {
        field2 = str;
    }
}

Weird, but still OK:

struct A
{
    public int field1;
    public string field2;

    public A(string str)
    {
        this = new A(); // in structs 'this' is assignable
        field2 = str;
    }
}

or

struct A
{
    public int field1;
    public string field2;

    public A(string str)
    {
        this = default(A); // in structs 'this' is assignable
        field2 = str;
    }
}

Upvotes: 6

brakeroo
brakeroo

Reputation: 1447

In your example, there is no behavioral change as this() calls the parameter-less constructor for the struct which is not defined.

Note that in C# 6.0 and newer you cannot re-define a struct's parameter-less constructor, so if you do:

public struct Example
{
    public Example() // compile error in c# 6.0 and up
    {
    }
}

You'll get a compile error. More details here.

In older versions of C# you can re-define the parameter-less constructor which means you may inject extra behavior in your parameterized constructor by modifying the parameter-less one.

Apart from this, there may be a theoretical performance hit due to the extra IL code generated for the this() constructor:

Example..ctor:
IL_0000:  ldarg.0     
IL_0001:  initobj     UserQuery.Example
IL_0007:  nop         
IL_0008:  ldarg.0     
IL_0009:  ldarg.1     
IL_000A:  call        UserQuery+Example.set_Number
IL_000F:  nop         
IL_0010:  ret 

Upvotes: 2

BlueTriangles
BlueTriangles

Reputation: 1204

UPDATED

For a class:

The difference is that the constructor that calls this() will also call the class's constructor that takes no arguments. So, for example, if this were your class:

public class Example
{
    public int Number { get; set; }

    public Example(int number) : this()
    {
        Number = number;
    }
    public Example()
    {
        Console.WriteLine("Hello");
    }
}

Then including this() would also print "Hello". This is a way you can chain constructors together, for code reuse.

For a struct:

You cannot add an empty constructor in a struct, so adding this() does not provide any benefit. Thanks to vendettamit for waking up my tired brain.

Upvotes: 2

Zazaeil
Zazaeil

Reputation: 4109

There is no difference. this() would call to a parameterless constructor, which is a must for structs by definition, which will not do anything unless you redefine it and customize its behavior. In case of structs you are not allowed to define your own parameterless constructor; with classes you can though.

However, please note that constructor chaining is a handy tool to DRY in a complicated construction scenarios: i.e. when object exposes numerous constructors with different parameters.

Upvotes: 1

Related Questions