c#写的代码,同样的代码用来随机生成数学题,为什么用Winform时候出来的内容都是重复的,用控制带程序就正常了?

c#写的代码,同样的代码用来随机生成数学题,为什么用Winform时候出来的内容都是重复的,用控制带程序就正常了?
版本是VS2022 .net6.0

winform一开始代码没有分到class里,我一开始是以为没有new一下不行,所以单独提出来了,控制台代码是直接复制过去的
这个是Winform代码:


```c#
 public partial class frmText : Form
    {
        public frmText()
        {
            InitializeComponent();
        }

        //30个10以内加减法
        private void button1_Click(object sender, EventArgs e)
        {
            Random r = new Random();
            string ret = "";
            for (int i = 0; i < 30; i++)
            {
                生成 a = new 生成();
                ret += a.生成2();
                ret += "\r\n";
            }
            textBox1.Text = ret;
        }

       
    }

    public class 生成
    {
        Random r = new Random();
        public string 生成2()
        {
            Random r = new Random();
            return r.Next(0, 10) > 5 ? 生成一个加法() : 生成一个减法();
        }

        string 生成一个加法()
        {
            
            int x = r.Next(0, 9);
            int y = r.Next(0, 9);
            if (x + y <= 15)
            {
                return (x.ToString() + " + " + y.ToString());
            }
            else
            {
                return 生成一个加法();
            }
        }

        string 生成一个减法()
        {
            int x = r.Next(0, 9);
            int y = r.Next(0, 9);
            if (x - y > 0)
            {
                return (x.ToString() + " - " + y.ToString());
            }
            else
            {
                return 生成一个减法();
            }
        }
    }



这个是控制台代码:

```c#
for (int i = 0; i < 64; i++)
{
    生成 s = new 生成();
    Console.WriteLine(s.生成2());
}

Console.WriteLine();


public class 生成
{
    Random r = new Random();
    public string 生成2()
    {
        Random r = new Random();
        return r.Next(0, 10) > 5 ? 生成一个加法() : 生成一个减法();
    }

    string 生成一个加法()
    {

        int x = r.Next(0, 9);
        int y = r.Next(0, 9);
        if (x + y <= 15)
        {
            return (x.ToString() + " + " + y.ToString() + " =");
        }
        else
        {
            return 生成一个加法();
        }
    }

    string 生成一个减法()
    {
        int x = r.Next(0, 9);
        int y = r.Next(0, 9);
        if (x - y > 0)
        {
            return (x.ToString() + " - " + y.ToString() + " =");
        }
        else
        {
            return 生成一个减法();
        }
    }
}

Random r = new Random();
要定义成全局变量,你放按钮里每次生成一个新的,那随机出来的数也是一样的

每生成一个数都new random方法的话,生成间隔太短会生成同一个数,但用同一个random生成多次,就会是随机的

原因貌似是因为在生成类构造函数中,每次创建生成对象时都会创建一个Random类的新实例。 这会导致生成内容的重复,因为 Random 类的种子值是基于当前系统时间的,如果两个 Random 实例的创建时间太接近,它们可能会以相同的种子值结束并产生 相同的随机数序列。
在控制台代码中,生成 对象是在循环中创建的,每次创建之间有一段时间,允许 Random 的每个实例具有不同的种子值并产生不同的随机数序列。
然而,在 Winform 代码中,生成对象是在 for 循环中快速连续创建的,这意味着 Random 的每个实例可能具有相同的种子值并产生相同的随机数序列。
为避免此问题,您应该在类级别而不是在生成类构造函数中创建 Random 的单个实例,并在整个生成类中使用该实例。 这将确保生成的每个实例都使用相同的 Random 实例并避免重复问题。
像这样:

public class gen
{
    private static Random r = new Random();

    public string gen2()
    {
        return r.Next(0, 10) > 5 ? genadd() : genless();
    }

    string genadd()
    {
        int x = r.Next(0, 9);
        int y = r.Next(0, 9);
        if (x + y <= 15)
        {
            return (x.ToString() + " + " + y.ToString());
        }
        else
        {
            return genadd();
        }
    }

    string genless()
    {
        int x = r.Next(0, 9);
        int y = r.Next(0, 9);
        if (x - y > 0)
        {
            return (x.ToString() + " - " + y.ToString());
        }
        else
        {
            return genless();
        }
    }
}