返回正确的对象

本文关键字:对象 返回 | 更新日期: 2023-09-27 18:26:15

我试图完成一个编程练习,但有一个测试失败了。我做错了什么?

任务是:

编写一个管理机器人工厂设置的程序。

当机器人从工厂的地板上下来时,他们没有名字。

第一次启动它们时,会生成一个随机名称,例如RX837或BC811。

每隔一段时间,我们就需要将机器人重置到工厂设置,这意味着它们的名称将被删除。下次你问,它有了一个新名字。

程序的测试如下所示,失败的是Different_robots_have_Different_names:

public class RobotNameTest
{
    private Robot robot;
    [SetUp]
    public void Setup()
    {
        robot = new Robot();
    }
    [Test]
    public void Robot_has_a_name()
    {
        StringAssert.IsMatch(@"[A-Z]{2}'d{3}", robot.Name);
    }
    [Test]
    public void Name_is_the_same_each_time()
    {
        Assert.That(robot.Name, Is.EqualTo(robot.Name));
    }
    [Test]
    public void Different_robots_have_different_names()
    {
        var robot2 = new Robot();
        Assert.That(robot.Name, Is.Not.EqualTo(robot2.Name));
    }
    [Test]
    public void Can_reset_the_name()
    {
        var originalName = robot.Name;
        robot.Reset();
        Assert.That(robot.Name, Is.Not.EqualTo(originalName));
    }
}

我的代码如下:

public class Robot
{
    private List<string> Names = new List<string>();
    private string name { get; set; }
    public string Name { get { return this.name; } }
    public Robot()
    {
        CreateName();
    }
    private void CreateName()
    {
        var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        var random = new Random();
        StringBuilder sb = new StringBuilder();
        sb.Append(
            new string(
                Enumerable.Repeat(chars, 3)
                    .Select(x => x[random.Next(x.Length)]).ToArray()
            )
        );
        sb.Append(random.Next(100, 999));
        if(Names.Any(word => word.Equals(sb.ToString())))
        {
            CreateName();
        }
        else
        {
            name = sb.ToString();
            Names.Add(sb.ToString());
        }
    }
    public void Reset()
    {
        this.name = "";
    }
}

返回正确的对象

使Names静态通过所有测试:

private static List<string> Names = new List<string>();

Static关键字表示在级别上创建成员,而不是对象。

在您的情况下,所有机器人都将共享一个链接到单个名称列表。删除static关键字将导致Names列表被创建为每个Robot对象。如果您想跟踪Robot构造函数被调用的次数,您可能应该有一个共享的名称列表,该列表在所有Robot对象之间共享。

测试失败是因为创建第二个对象时,它有一个新的空名称列表,而第一个Robot类对此一无所知。所以在您的情况下,Names.Any(...)总是返回false。

要阅读更多详细信息,请考虑上面的msdn链接。

错误并不明显。Random类使用从当前系统时间创建的随机种子进行初始化。与CPU时钟频率相比,产生系统时间的手表滴答声较慢。因此,如果new Random()被调用两次fast,则random很可能用相同的种子被初始化两次。

解决方案:将random声明为静态,并只初始化一次。

public class Robot
{
    private static Random random = new Random();
    ...
}

现在,无论您创建了多少个机器人,random都只创建一次。