结构构造函数:"在将控制权返回给调用者之前,必须完全分配字段."

Nic*_*ner 106 c# constructor struct

这是我想写的结构:

  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; }
        }
Run Code Online (Sandbox Code Playgroud)

这会导致以下编译错误:

在分配所有字段之前,不能使用"this"对象

在将控制权返回给调用者之前,必须完全分配字段'AttackTraits.probability'

在将控制权返回给调用者之前,必须完全分配自动实现的属性"AttackTraits.Damage"的备份字段.考虑从构造函数初始化程序中调用默认构造函数.

在将控制权返回给调用者之前,必须完全分配自动实现的属性"AttackTraits.Distance"的备份字段.考虑从构造函数初始化程序中调用默认构造函数.

我究竟做错了什么?

Chr*_*ckx 294

如果在具有自动属性的结构上看到此错误,只需通过: this()以下示例从参数化的构造函数中调用无参数构造函数:

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

  public MyStruct(int someVal) : this()
  {
     this.SomeProp = someVal;
  }
}
Run Code Online (Sandbox Code Playgroud)

通过从构造函数声明中调用this(),您可以让基类ValueType类初始化自动属性的所有支持字段.我们无法在构造函数上手动执行此操作,因为我们无法访问自动属性的支持字段.ValueType是所有结构的基类.

  • @DarrenHale当构造函数的第一行要执行时,对于结构,需要已经初始化所有字段.SomeProp是一个自动属性,相当于具有显式的'someProp'字段和get/set方法.通过调用base无参数:this()构造函数,您可以保证在构造函数中"您的逻辑"的第一行之前,所有字段都已初始化. (8认同)
  • @ChrisAmelinckx你在哪里找到所有这些东西它看起来像某种想象力虽然只是它适用于真实(: (4认同)
  • 很酷,我们有一个解决方案,但为什么这个解决方案需要呢? (3认同)
  • @Peter,你提出了一个很好的观点,这似乎是一个解决方法。我的观点是,这不是解决方法,而是问题的完整解决方案。结构体是应用程序状态的轻量级表示,可以在执行堆栈上复制。(每次将值类型实例(结构)传递到方法时,都会在该方法的上下文中创建它的新副本,而不是传递类定义的对象类型的引用)。 (2认同)

vit*_*ore 51

尝试访问概率字段而不是访问者.在这种情况下,自动道具应该也可以.

结构体无法使用无参数构造函数,因此请考虑将其更改为类.

最佳做法是仅在结构为16个字节或更少且不可变时使用结构.因此,如果您要在创建后更改对象字段,请考虑将其重构为类.

此外,您可以将构造函数定义更改为:

construct(params) : this()
Run Code Online (Sandbox Code Playgroud)

这也将删除错误

  • 仅供参考,您的回答是有效的,但您的一些理由是不正确的.事实上,结构总是有一个无参数构造函数.与类不同,通过创建带参数的构造函数,无法隐藏struct的无参数构造函数. (4认同)
  • 不要不必要地考虑这一点,但不仅仅是调用构造函数是完全合法的,而且它会像任何其他构造函数一样弹出intellisense.你能提供一个不真实的案例吗? (2认同)

Tho*_*que 31

您正在probability通过Probability属性设置字段,但编译器不知道该属性设置字段...因此您需要显式初始化概率字段本身

public AttackTraits(double probability, int damage, float distance)
{
    this.probability = 0;
    Distance = distance;
    Damage = damage;
}
Run Code Online (Sandbox Code Playgroud)

  • @RogerWillcocks,只需调用默认构造函数:`public YourStruct(some params):this()`(参见vittore的回答) (45认同)
  • 这个解决方案的问题.您没有Probability属性的验证权益.并且它不能解决所有问题,因为您还需要将"距离"和"损坏"更改为非匿名属性,否则它将无法正常工作.我更喜欢@ Chris-Amelinckx的答案作为更好的解决方案. (2认同)