tags:

views:

383

answers:

3

Given the following code:

public struct Foo
{
    public Foo(int bar, int baz) : this()
    {
        Bar = bar; // Err 1, 2
        Baz = baz; // Err 3
    }

    public int Bar { get; private set; }
    public int Baz { get; private set; }
}

What does : this() actually do? There is no default constructor, so what is it calling? Without this addendum, the whole thing crashes with errors.

Error   1 The 'this' object cannot be used before all of its fields are assigned to
Error   2 Backing field for automatically implemented property 'Foo.Bar' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
Error   3 Backing field for automatically implemented property 'Foo.Baz' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
+7  A: 

Form here

So why is a struct constructor with no arguments not permitted in C#? This is because structs already contain a default constructor which has no arguments. Keep in mind that this default constructor is part of the .Net framework, therefore it is not visible in our code. The sole purpose of the default constructor is to assign default values to its members.

Basically, all structs have a default constructor already. The situation would be different with a class.

George Mauer
Any thoughts on why I need to call the default constructor and can't just initialise all the properties manually in my constructor?
Matthew Scharley
And this is specifically an issue when assigning *properties* in the constructor. Constructors which initialise all the backing *fields* themselves don't need to call the default constructor. But because a property setter is a full-blown method, C# requires the fields to be fully initialised before the setter can be called. And with auto properties the only way to do that is via the chain to the default constructor.
itowlson
+1  A: 

this discusses why they added this extra check.

Locksfree
+3  A: 

As you are using the shortcut for properties, you can only access the properties through their setters and getters. However, before all fields has been assigned, you are not allowed to call any of the setters. A workaround for this is to call the parameterless constructor that is created automatically, that initialised the fields. This of course means that you are initialising the fields twice.

When I was faced with this problem a few days ago I just removed the shortcut for properties, and declared the local variables myself so that I could set them in the constructor:

public struct Foo {

   public Foo(int bar, int baz) {
      _bar = bar;
      _baz = baz;
   }

   private int _bar, _baz;

   public int Bar { get { return _bar; } }
   public int Baz { get { return _baz; } }

}
Guffa
Why is initializing the fields twice such a bad thing? I think it's a reasonable workaround, and I doubt it'd matter performance-wise (although I haven't checked).
configurator
@configurator: If you are using a struct it's usually for performance reasons, so if you are wasting time initializing the fields twice, you should at least be aware of it.
Guffa