Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Struct constructor: "fields must be fully assigned before control is returned to the caller."

Here is a struct I am trying to write:

  public struct AttackTraits
        {
            public AttackTraits(double probability, int damage, float distance)
            {
                Probability = probability;
                Distance = distance;
                Damage = damage;
            }

            private double probability;
            public double Probability
            {
                get
                {
                    return probability;
                }
                set
                {
                    if (value > 1 || value < 0)
                    {
                        throw new ArgumentOutOfRangeException("Probability values must be in the range [0, 1]");
                    }
                    probability = value;
                }
            }

            public int Damage { get; set; }

            public float Distance { get; set; }
        }

This results in the following compilation errors:

The 'this' object cannot be used before all of its fields are assigned to

Field 'AttackTraits.probability' must be fully assigned before control is returned to the caller

Backing field for automatically implemented property 'AttackTraits.Damage' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.

Backing field for automatically implemented property 'AttackTraits.Distance' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.

What am I doing wrong?

like image 279
Nick Heiner Avatar asked Mar 28 '10 23:03

Nick Heiner


3 Answers

If you see this error on a struct that has an automatic property, just call the parameterless contructor from your parameterized one by doing : this() example below:

struct MyStruct
{
  public int SomeProp { get; set; }

  public MyStruct(int someVal) : this()
  {
     this.SomeProp = someVal;
  }
}

By calling :this() from your constructor declaration you let the base ValueType class initialize all the backing fields for the automatic properties. We cannot do it manually on our constructor because we don't have access to the backing field of an automatic property. ValueType is the base class of all structs.

like image 137
Chris Amelinckx Avatar answered Oct 21 '22 13:10

Chris Amelinckx


try to access probability field not accessor. In this case auto-props should work as well.

There is no way for a struct to have parameterless constructor so consider change it to class instead.

Best practise is to use structs only if they are 16 bytes or less and are immutable. So if you are going to change object fields after creating, consider refactoring it to class.

Also, you can change constructor definition to:

construct(params) : this()

this will remove error as well

like image 51
vittore Avatar answered Oct 21 '22 13:10

vittore


You're setting the probability field through the Probability property, but the compiler doesn't know that the property sets the field... so you need to explicitly initialize the probability field itself

public AttackTraits(double probability, int damage, float distance)
{
    this.probability = 0;
    Distance = distance;
    Damage = damage;
}
like image 33
Thomas Levesque Avatar answered Oct 21 '22 15:10

Thomas Levesque