1

Есть две формы, один класс. С основной формы открываю вторую:

private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            this.Hide();
            form2.ShowDialog();
            this.Close();
        }

В дополнительном классе я так же создаю объект на вторую форму

Form2 form2 = new Form2();

И вот на эту строку выдаёт исключение System.StackOverflowException. Больше я нигде не создаю объект на вторую форму. Как можно обойти эту проблемку? Ведь мне нужно через методы этого класса изменять компоненты на второй форме. Вот весь код:

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form2 = new Form2();
        this.Hide();
        form2.ShowDialog();
        this.Close();
    }
}

public partial class Form2 : Form { Ans ans = new Ans(); private int index = -1;

    public Form2()
    {
        InitializeComponent();
        ans.Test(radioButton1, radioButton2);

        Shown += Form1_Shown15;
    }

    private void radioButton_Click(object sender, EventArgs e)
    {
        RadioButton button = sender as RadioButton;

        if (button == radioButton1) { index = 0; }
        if (button == radioButton2) { index = 1; }
    }

    private async void Form1_Shown25(object sender, EventArgs e)
    {
        verticalProgressBar1.Value = 100;
        for (int i = 25 * 60; i > 0; i--)
        {
            verticalProgressBar1.Value = i * 100 / (25 * 60);
            await Task.Delay(1000);
        }
        Close();
    }

    private void button3_Click(object sender, EventArgs e)
    {
        try
        {
            ans.Correct(index);

            radioButton1.Checked = false;
            radioButton2.Checked = false;

            index = -1;
        }
        catch { return; }

        ans.Index++;

        if (ans.Index > 47)
        {
            MessageBox.Show();
            return;
        }
        ans.Test(radioButton1, radioButton2);
    }
}

public class Ans { Form2 form2 = new Form2();

    private List<string> test = new List<string>()
    { };

    private bool[,] boolTest =
    { };

    public int correct = 0;

    public int TestIndex { get; set; }
    public int Index { get; set; }

    public string GetCorrect { get; set; }

    public void Test(Control control1, Control control2)
    {
        control1.Text = test[TestIndex];
        TestIndex++;
        control2.Text = test[TestIndex];
        TestIndex++;
    }

    public void Correct(int i)
    {
        SystemSounds.Exclamation.Play();
        #region 1-10
        //1
        if (Index == 0)
        {
            if (boolTest[0, i] == true)
            {
                form2.pictureBox2.BackColor = Color.Green;
                form2.label2.Text = "";
                correct++;
                return;
            }
            else
            {
                form2.pictureBox2.BackColor = Color.Red;
                form2.label2.BackColor = Color.Red;
            }
        }           
    }
}

1 Answers1

4

Здесь всё просто, при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans.

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

А при создании Form2 происходит

Ans ans = new Ans(); // создание новой копии объекта на основе класса Ans

А при создании класса Ans просходит

Form2 form2 = new Form2(); // создание новой копии Form2

...и так далее


И каждый такой вызов помещает точку возврата в стек. Стек хранит место, куда возвращаться, ведь когда вы пишете return или метод заканчивается, процессор достает из того самого стека указатель, куда возращаться.

А у вас вызов в вызове в вызове и т.д.. И всё это попадает в стек. Но у стека есть размер, обычно это 1 мегабайт. Так как вы вечно продолжаете туда добавлять точки возрата (бесконечная рекурсия), стек переполняется, и вы получаете StackOverflowException.

Типичный пример бесконечной рекурсии

void MyMethod()
{
    MyMethod();
}

А ваш случай выглядит вот так

void MyMethod1()
{
    MyMethod2();
}

void MyMethod2() { MyMethod1(); }

Не создавайте новую форму в классе Ans, используйте существующую.

public partial class Form2 : Form
{
    Ans ans;
public Form2()
{
    InitializeComponent();
    ans = new Ans(this);
    ans.Test(radioButton1, radioButton2);

    Shown += Form1_Shown15;
}

}

public class Ans { Form2 form2;

public Ans(Form2 f2)
{
    form2 = f2;
}

}

aepot
  • 49,560
  • 1
    Спасибо Вам большое, Вы часто меня выручаете! – Ярослав Овчар Apr 10 '21 at 10:43
  • @ЯрославОвчар разберите этот ответ и все примеры в нём. Что, почему и как работает. Еще пересаньте писать свой код в конструкторе формы, вместо этого используйте обработчик события Form.Load. – aepot Apr 10 '21 at 10:46
  • 1
    На примере всё ясно, советам последую, ещё раз спасибо) – Ярослав Овчар Apr 10 '21 at 10:52
  • 4
    Шикарный ответ: и по делу и с юмором! – A K Apr 10 '21 at 12:22