我需要从非静态类构造函数中的非静态类引用变量。 [c#]

时间:2018-06-29 17:17:31

标签: c# class constructor static non-static

我正在尝试用天然卫星制作一个太阳系。目前,我正在相对于静态“ Sun”类对象绘制行星,但是我很想让该类使用另一个行星对象的位置并相对于该行星进行绘制。为此,我需要提取该行星对象的x和y位置。

这是我用来绘制行星的类的类构造函数。

Nebesko_Telo merkur = new Nebesko_Telo(Sun.x, Sun.y, 4, 12, 4.090909090909091,
                                       1, 255, 255, 255);
// A field initializer cannot reference the non-static field, method,
//    or property 'Form1.merkur'.
Nebesko_Telo venera = new Nebesko_Telo(merkur.x, merkur.y, 1, 23, 1.5, 1, 176, 108, 32);

这是类的构造函数。

public Nebesko_Telo(doubl _rel_tel_x, double _rel_tel_y, double _r, double _or,
                    double _Fi_mult, double _tilt_plant_nat, int _re, int_gr, int _bl) {
    r = _r;
    or = _or;
    Fi_mult = _Fi_mult;
    re = _re;
    gr = _gr;
    bl = _bl;
    tilt_planet_nat = _tilt_planet_nat;
    rel_tel_x = _rel_tel_x;
    rel_tel_y = _rel_tel_y;
}

x和y位置随着每个刻度线不断更新,因此我需要它不断更新:^ /。

3 个答案:

答案 0 :(得分:5)

在字段初始值设定项中以 any 方式使用this是非法的。 merkur的初始值设定项中的venera实际上是this.merkur,因此很重要。

C#阻止了这种情况,因为该技术是错误的常见来源。字段初始化程序在构造器主体之前运行,包括基类构造器的构造主体。如果C#没有限制您访问this,则访问属性或调用尚未准备好使用的方法将非常容易。

有关构造函数初始化程序运行顺序的更多详细信息,请参见https://blogs.msdn.microsoft.com/ericlippert/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one/

您应该做的是将所有字段初始化程序移到构造函数主体中。然后,您有责任确保主体中的语句以正确的顺序运行以执行所需的初始化。

答案 1 :(得分:0)

simple Google search中的第一个匹配项应该可以解决此问题。

本质上,您的问题是您正在使用一个实例变量(merkur)在代码中初始化另一个实例变量(venera)。

这是不允许的,因为不能保证merkur会在venera之前初始化,因此编译器不喜欢这样。

假设merkur.xSun.x相同,您也可以使用它来初始化venera

答案 2 :(得分:0)

编译器不允许您使用另一个实例的属性来初始化一个实例字段。相反,我建议在首先执行的任何方法(例如Form.Load事件)中初始化您的字段。这将允许您在使用字段处理任何信息之前正确初始化它们。例如:

Nebesko_Telo merkur = null;
Nebesko_Telo venera = null;
private void Form1_Load(object sender, EventArgs e) {
    merkur = new Nebesko_Telo(Sun.x, Sun.y, 4, 12, 4.090909090909091, 1, 255, 255, 255);
    if (merkur != null)
        venera = new Nebesko_Telo(merkur.x, merkur.y, 1, 23, 1.5, 1, 176, 108, 32);
}

绝对可以参考其他答案提供的文章,this post也应阐明该主题,因为那里的已接受答案提供了有关此问题为何是实际问题的一些详细信息。引用以防万一链接消失:

  

您不能使用实例变量来初始化另一个实例变量。为什么?因为编译器可以重新排列它们-无​​法保证reminder将在defaultReminder之前初始化,所以上面的行可能在运行时抛出NullReferenceException

也可以随时查看Microsoft的Compiler Error CS0236参考。这应该使该主题更具启发性。

  

实例字段不能用于初始化方法外的其他实例字段。如果要在方法外部初始化变量,请考虑在类构造函数内执行初始化。有关更多信息,请参见Methods