7

I have following code which is not allowed (error below), why?

    struct A
    {
        private int b;

        public A(int x)
        {
            B = x;
        }
        public int B
        {
            get { return b; }
            set { b=value; }
        }

    }

I receive the following error:

The 'this' object cannot be used before all of its fields are assigned to Field 'Test.x' must be fully assigned before control is returned to the caller

NakedBrunch
  • 48,713
  • 13
  • 73
  • 98
Mocco
  • 1,183
  • 2
  • 12
  • 25

2 Answers2

6

A struct's variables all have to be definitely assigned before you can use any methods or properties. There are two possible fixes here:

1) You can explicitly call the parameterless constructor:

public A(int x) : this()
{
    B = x;
}

2) You can use the field instead of the property:

public A(int x)
{
    b = x;
}

Of course the second option only works in your current form - you have to use the first option if you want to change your struct to use an automatic property.

However, importantly, you now have a mutable struct. This is almost always a very bad idea. I would strongly urge you to use something like this instead:

struct A
{
    private readonly int b;

    public A(int x)
    {
        b = x;
    }

    public int B { get { return b; } }
}

EDIT: More details of why the original code doesn't work...

From section 11.3.8 of the C# spec:

If the struct instance constructor doesn't specify a constructor initializer, the this variable corresponds to an out parameter of the struct type

Now initially that won't be definitely assigned, which means you can't execute any member function (including property setters) until all the firsts of the struct being constructed have been definitely assigned. The compiler doesn't know or try to take account of the fact that the property setter doesn't try to read from another field. It's all in aid of avoiding reading from fields which haven't been definitely assigned.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Well I do not understand. What is the difference between setting to property which does the same (b=value) and doing it manually? Still I cannot see why B=x does not work. BTW struct variables are fields or I should call them variables? – Mocco Mar 01 '11 at 11:48
  • @Cocodrilo - because you can't do *anything* with a struct until it is fully initialised, which can be by calling the default (and, as it happens, fake) constructor, or can be by assigning all the fields explicitly. You can't access a property (which is a method) until that is done. "1" above shows the first option (constructor), "2" above shows the "assign all the fields" option. – Marc Gravell Mar 01 '11 at 11:50
  • @Cocodrilo and just to second Jon's point; mutable structs are very very bad mojo. – Marc Gravell Mar 01 '11 at 11:52
  • @Cocodrilo: See my edit - it's really useful to read the C# spec for this, to be honest. – Jon Skeet Mar 01 '11 at 11:53
  • Well I am now lost. What is bad on mutable struct? I thought I could work with it just like with class (except for being a value type) – Mocco Mar 01 '11 at 11:59
  • @Cocodrilo: Just one example: http://blogs.msdn.com/b/ericlippert/archive/2008/05/14/mutating-readonly-structs.aspx See also http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil and various other questions, blog posts etc. – Jon Skeet Mar 01 '11 at 12:00
  • 1
    @Cocodrilo, just because **you** know that the setter just sets the field, don't assume that the compiler knows too. As far as it's concerned B=x calls a method (like *set_B(x)*) and that method could do anything at all, including accessing other fields, that might have not been initialized. – SWeko Mar 01 '11 at 12:03
0

Change your constructor to:

public A(int x) :
    this()
{
    B = x;
}

As to "why", refer to 11.3.8 Constructors and 5.3 Definite assignment.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • @Gunner : This code will remove this error If not you will have an error as The 'this' object cannot be used before all of its fields are assigned – Developer Mar 01 '11 at 11:49