views:

642

answers:

4

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?

+1  A: 

If you assign to Probability a value outside the range [0,1], this.probability is never set.

The compiler expects this.probability to have a value in all cases, even if an exception is thrown. You can work around this by simply setting this.probability to a "default" value before throwing the exception.

Mark Rushakoff
+2  A: 

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;
            Probability = probability;
            Distance = distance;
            Damage = damage;
        }
Thomas Levesque
+2  A: 

Change the line "Probability = probability" to "this.probability = probability"

In the future pick a different naming convention for fields as you do for parameters. For example, prefix all fields with an underscore, so you can simply call this:

_probability = probability;

and see easily what's happening.

David Morton
but it won't perform the validity check done in the property setter...
Thomas Levesque
Yes, there simply is an ugly name conflict between a parameter and a field.
Henk Holterman
A: 

try to access probability field not accessor. in this case autoprops should work as well. Also there is no way for struct to have paramless constructor so consider change it to class instead. There is a rule that one should use structs only if they are not bigger than 16 bytes and are immutable. So if you are going to change object fields after creation change it to class. also you can change costructor definition to

construct(params) : this()

in this case you won't have this errors as well

vittore