web-dev-qa-db-fra.com

Constructeur de structures: "les champs doivent être entièrement attribués avant que le contrôle ne soit renvoyé à l'appelant."

Voici une structure que j'essaie d'écrire:

  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; }
        }

Il en résulte les erreurs de compilation suivantes:

L'objet "this" ne peut pas être utilisé avant que tous ses champs soient affectés à

Le champ 'AttackTraits.probability' doit être entièrement attribué avant que le contrôle ne soit renvoyé à l'appelant

Le champ de sauvegarde pour la propriété implémentée automatiquement "AttackTraits.Damage" doit être entièrement attribué avant que le contrôle ne soit renvoyé à l'appelant. Pensez à appeler le constructeur par défaut à partir d'un initialiseur de constructeur.

Le champ de sauvegarde pour la propriété implémentée automatiquement "AttackTraits.Distance" doit être entièrement attribué avant que le contrôle ne soit renvoyé à l'appelant. Pensez à appeler le constructeur par défaut à partir d'un initialiseur de constructeur.

Qu'est-ce que je fais mal?

103
Nick Heiner

Vous définissez le champ probability via la propriété Probability, mais le compilateur ne sait pas que la propriété définit le champ ... vous devez donc initialiser explicitement le champ de probabilité lui-même

public AttackTraits(double probability, int damage, float distance)
{
    this.probability = 0;
    Distance = distance;
    Damage = damage;
}
30
Thomas Levesque

Si vous voyez cette erreur sur une structure qui a une propriété automatique, il suffit d'appeler le constructeur sans paramètre à partir de celui paramétré en faisant : this() exemple ci-dessous:

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

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

En appelant: this () à partir de votre déclaration de constructeur, vous laissez la classe ValueType de base initialiser tous les champs de sauvegarde pour les propriétés automatiques. Nous ne pouvons pas le faire manuellement sur notre constructeur car nous n'avons pas accès au champ de support d'une propriété automatique. ValueType est la classe de base de toutes les structures.

289
Chris Amelinckx

essayez d'accéder au champ de probabilité et non à l'accesseur. Dans ce cas, les accessoires automatiques devraient également fonctionner.

Il n'y a aucun moyen pour une structure d'avoir un constructeur sans paramètre, alors pensez plutôt à le changer en classe.

La meilleure pratique consiste à utiliser des structures uniquement si elles sont de 16 octets ou moins et sont immuables. Donc, si vous souhaitez modifier les champs d'objet après leur création, envisagez de le refactoriser en classe.

Vous pouvez également modifier la définition du constructeur en:

construct(params) : this()

cela supprimera également l'erreur

49
vittore

Changez la ligne Probability = probability à this.probability = probability

À l'avenir, choisissez une convention de dénomination différente pour les champs comme pour les paramètres. Par exemple, préfixez tous les champs avec un trait de soulignement, vous pouvez donc simplement appeler ceci:

_probability = probability;

et voir facilement ce qui se passe.

2
David Morton