递归调用方法忽略检查并跳过断点

Recursively calling a method ignores checks and skips breakpoints

我目前正在开发一个聊天服务器作为学校项目。 我对服务器上的名称有一些条件,所以我创建了一个调用方法来执行这些规则。 任何时候一个名字是不可接受的。该方法将再次调用它自己。 除其他外,该方法应该可以防止人们使用相同的名字。

我启动服务器,为 client1 远程登录。然后我将 client1 的名称设置为:bob

然后我远程登录到 client2 的服务器。如果我尝试将名称设置为 bob,它会被拒绝——这是应该的。 如果我然后将名称设置为 bobby,它就会被接受。该方法完成并设置名称。

奇怪的部分来了。将名称设置为可用的有效名称后,名称再次更改。到我试过的第一个(不可用的)名字 (bob)。

所以我尝试了一些断点,认为我在递归调用该方法时犯了一个错误。但是在名称更改为 bob 的直通中,它不会激活我放在 reader 上的断点,也不会激活应防止将名称设置为不可用名称的检查。

我的代码:

class NameHandler
{
    private readonly List<string> AllNames = new List<string>();

    public void SetName(StreamWriter writer, Client client)
    {
        var reader = new StreamReader(new NetworkStream(client.GetSocket));
        var name = reader.ReadLine();

        if(!IsNameAvailable(name))
        {
            writer.WriteLine("That name is in use. Pick an other one");
            SetName(writer, client);
        }

        try
        {
            client.Name = name;
        }
        catch(ArgumentOutOfRangeException)
        {
            writer.WriteLine("Max length of name is 10.");
            writer.WriteLine("Try again please:");
            SetName(writer, client);
        }
        catch(ArgumentNullException)
        {
            writer.WriteLine("Invalid name");
            writer.WriteLine("Try again please:");
            SetName(writer, client);
        }
        catch (ArgumentException)
        {
            writer.WriteLine("The name may not contain spaces");
            writer.WriteLine("Try again please:");
            SetName(writer, client);
        }
        AllNames.Add(client.Name.ToLower());
        writer.WriteLine("Your name was successfully updated.");
    }

    private bool IsNameAvailable(string name)
    {
        return !AllNames.Contains(name.ToLower());
    }
}

客户端 class 包含在实例化时传递给它的唯一套接字。 每个客户端都有自己唯一的本地端口。这已被多次验证。

问题是在 SetNamebobby 成功完成后,它 returns 到调用它的地方,即这里:

if(!IsNameAvailable(name))
{
    writer.WriteLine("That name is in use. Pick an other one");
    SetName(writer, client); //Control returns to here
}

局部name变量仍然设置为bob,然后执行下一段代码:

try
{
    client.Name = name;
}

正在将 Name 属性 设置为您已经发现不可用的那个。简单的解决方法是在您再次递归调用 SetName 后立即将 return 退出函数:

if(!IsNameAvailable(name))
{
    writer.WriteLine("That name is in use. Pick an other one");
    SetName(writer, client);
    return;
}

这样当控制 returns 到外部函数时,它将立即 return 而不会尝试进一步更改名称。您可能也需要在异常处理程序中的每个调用之后立即 return。

我认为您遗漏了 else 部分。赋值 client.Name = name; 总是在递归调用的函数 returns 之后执行,即使名称是 "not available"。我认为这不是故意的。