web-dev-qa-db-ja.com

構造体コンストラクター:「フィールドを完全に割り当ててからでないと、制御は呼び出し元に返されません。」

ここに私が書いている構造体があります:

  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」オブジェクトは、そのすべてのフィールドが割り当てられるまで使用できません

制御が呼び出し元に返される前に、フィールド「AttackTraits.probability」を完全に割り当てる必要があります

自動的に実装されるプロパティ「AttackTraits.Damage」のバッキングフィールドは、制御が呼び出し元に返される前に完全に割り当てられる必要があります。コンストラクター初期化子からデフォルトのコンストラクターを呼び出すことを検討してください。

自動的に実装されるプロパティ「AttackTraits.Distance」のバッキングフィールドは、制御が呼び出し元に返される前に完全に割り当てられる必要があります。コンストラクター初期化子からデフォルトのコンストラクターを呼び出すことを検討してください。

何が間違っていますか?

103
Nick Heiner

probabilityプロパティを介してProbabilityフィールドを設定していますが、プロパティがフィールドを設定することをコンパイラが認識していません...したがって、確率フィールド自体を明示的に初期化する必要があります

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

自動プロパティを持つ構造体でこのエラーが表示される場合は、以下の: this()の例を実行して、パラメーター化されたコンストラクターからパラメーターなしのコンストラクターを呼び出すだけです。

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

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

コンストラクター宣言から:this()を呼び出すことにより、ベースValueTypeクラスに自動プロパティのすべてのバッキングフィールドを初期化させます。自動プロパティのバッキングフィールドにアクセスできないため、コンストラクタで手動で行うことはできません。 ValueTypeは、すべての構造体の基本クラスです。

289
Chris Amelinckx

アクセサではなく確率フィールドにアクセスしてみてください。この場合、自動小道具も動作するはずです。

構造体がパラメーターなしのコンストラクターを持つ方法はないため、代わりにクラスに変更することを検討してください。

ベストプラクティスは、16バイト以下で不変の場合にのみ構造体を使用することです。したがって、作成後にオブジェクトフィールドを変更する場合は、クラスにリファクタリングすることを検討してください。

また、コンストラクター定義を次のように変更できます。

construct(params) : this()

これによりエラーも削除されます

49
vittore

行を変更しますProbability = probabilityからthis.probability = probability

将来的には、パラメータの場合と同様に、フィールドに別の命名規則を選択してください。たとえば、すべてのフィールドの前にアンダースコアを付けると、次のように簡単に呼び出すことができます。

_probability = probability;

何が起きているかを簡単に確認できます。

2
David Morton