Мне нужно ссылаться на переменную из нестатического класса в конструкторе нестатического класса. [C #] - PullRequest
0 голосов
/ 29 июня 2018

Я пытаюсь сделать солнечную систему с естественными спутниками. В настоящее время я рисую планеты относительно статического объекта класса "Солнце", но я бы хотел, чтобы класс использовал положение другого объекта планеты и рисовал относительно этой планеты. Для этого мне нужно извлечь координаты 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 голосов
/ 29 июня 2018

Запрещено использовать 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/ для более подробной информации о порядке запуска инициализаторов конструктора.

Что вам нужно сделать, это переместить все ваши инициализаторы полей в тело конструктора. Затем вы несете ответственность за то, чтобы операторы в теле выполнялись в правильном порядке для выполнения желаемой инициализации.

0 голосов
/ 29 июня 2018

Компилятор не позволит вам инициализировать одно поле экземпляра свойствами другого. Вместо этого я бы порекомендовал инициализировать ваши поля внутри любого метода, который выполняется первым (например, событие 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);
}

Определенно не стесняйтесь ссылаться на статьи, предоставленные другими ответами, этот пост также должен пролить некоторый свет на эту тему, поскольку принятый ответ дает некоторые хорошие детали относительно того, почему эта проблема является актуальной проблемой , Цитировать, если ссылка когда-либо умрет:

Нельзя использовать переменную экземпляра для инициализации другой переменной экземпляра. Зачем? Поскольку компилятор может переставить их - нет гарантии, что reminder будет инициализирован до defaultReminder, поэтому в приведенной выше строке может быть выдан NullReferenceException во время выполнения.

Также не стесняйтесь обращаться к справке Compiler Error CS0236 от Microsoft. Это должно пролить дополнительный свет на эту тему.

Поля экземпляра нельзя использовать для инициализации других полей экземпляра вне метода. Если вы пытаетесь инициализировать переменную вне метода, попробуйте выполнить инициализацию внутри конструктора класса. Для получения дополнительной информации см. Методы .

0 голосов
/ 29 июня 2018

Первое попадание в простом поиске Google должно решить эту проблему.

По сути, ваша проблема в том, что вы используете одну переменную экземпляра (merkur) для инициализации другой переменной экземпляра (venera) в своем коде.

Это недопустимо, поскольку нет гарантии, что merkur будет инициализирован до venera, поэтому компилятору это не нравится.

Предполагая, что merkur.x совпадает с Sun.x, вы также можете использовать его для инициализации venera.

...