【问题标题】:C# Object Duplication In List列表中的 C# 对象重复
【发布时间】:2013-04-21 01:02:23
【问题描述】:

我正在尝试使用对象列表创建一个简单的模拟,并使其重复执行计算以代表一个农民。它有一种方法可以随机增加农民的钱数,每个农民从 100 美元开始

    public class Farmer
    {
    public decimal money { get; set; }

    public Farmer()
    {
        money = 100;
    }

    public void doOneYear() //Represents how much money the farmer earned
    {
        Random random = new Random();
        decimal growth = random.Next(0, 100);
        decimal percentage = (growth / 1000);
        money = money * (1 + percentage);
    }
}

运行的代码是这样的

        List<Farmer> farmers = new List<Farmer>();

        int count = 0;

        while (count < 10)
        {
            Farmer newFarmer = new Farmer();
            farmers.Add(newFarmer);
            count++;
        }


        foreach(var farmer in farmers)
        {
            int years = 0;
            while (years < 10)
            {
                farmer.doOneYear();
                years++;
            }
        }


        foreach (var farmer in farmers)
        {
            MessageBox.Show(farmer.money.ToString());
        }

但是我得到的结果只是重复列表中的第一个对象。如果我在调试模式下逐步完成整个过程,它可以正常工作,但是当我让它运行时,对象似乎是重复的。

【问题讨论】:

标签: c# list random


【解决方案1】:

来自 MSDN:“默认种子值源自系统时钟并且具有有限分辨率。因此,通过调用默认构造函数连续创建的不同 Random 对象将具有相同的默认种子值,并且,因此,将产生相同的随机数集。”

我个人只是将 Random 实例设为静态成员:

public class Farmer
{
    public decimal money { get; set; }
    private static Random random = new Random();

    public Farmer()
    {
        money = 100;
    }

    public void doOneYear() //Represents how much money the farmer earned
    {
        decimal growth = random.Next(0, 100);
        decimal percentage = (growth / 1000);
        money = money * (1 + percentage);
    }
}

【讨论】:

    【解决方案2】:

    由于程序运行得如此之快,而且我相信 Random 类使用时间设置作为其默认种子,因此您需要自己将种子注入 Random 调用。 (这也可能是您在调试时会看到不同数字的原因 - 您使程序运行速度变慢,因此 Random 类会输出不同的数字。

    我是这样做的,并且在输出中看到每个农民的不同数字。不过,您可能希望使用不同的种子生成。

        public class Farmer
        {
            private static int seed = 17;
    
            public decimal money { get; set; }
            public int FarmerID { get; set; }
            public Farmer(int id)
            {
                money = 100;
                FarmerID = id;
            }
    
            public void doOneYear() //Represents how much money the farmer earned
            {
                seed++;
                Random random = new Random(seed);
                decimal growth = random.Next(0, 100);
                decimal percentage = (growth / 1000);
                money = money * (1 + percentage);
            }
        }
    

    【讨论】:

    • 对种子使用编译时常量将导致程序为每次运行提供相同的随机值。静态/全局/传递给构造函数的随机实例通常是一种更好的方法(除非每次都有相同的结果是你想要的)。
    • 请注意,我显示的代码在使用种子之前会对其进行递增。我实际上运行了代码,它为农民提供了不同的数字。也就是说,正如我在回答中指出的那样,他应该考虑不同的种子一代——我的简化回答只是为了回答他提出的问题。
    • 是的,他们会为每个农民提供不同的数字,但如果你运行程序 10 次,农民 1 将始终拥有与其他 9 次相同的数字(农民 2 和 3 ETC。)。这就是在种子中使用时间的原因(这是默认构造函数所做的)。您可以简单地将种子更改为基于时间的东西,例如 private static int seed = DateTime.Now.Milliseconds; 来实现这一点。
    • 同意,如前所述,这不是理想的种子生成。但如果 OP 选择询问,那将是一个单独的问题。
    • 我并没有停下来思考随机值是如何生成的,我在想我在列表中做错了什么并且发疯了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2013-04-18
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多