递归调用方法忽略检查并跳过断点
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 包含在实例化时传递给它的唯一套接字。
每个客户端都有自己唯一的本地端口。这已被多次验证。
问题是在 SetName
与 bobby
成功完成后,它 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"。我认为这不是故意的。
我目前正在开发一个聊天服务器作为学校项目。 我对服务器上的名称有一些条件,所以我创建了一个调用方法来执行这些规则。 任何时候一个名字是不可接受的。该方法将再次调用它自己。 除其他外,该方法应该可以防止人们使用相同的名字。
我启动服务器,为 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 包含在实例化时传递给它的唯一套接字。 每个客户端都有自己唯一的本地端口。这已被多次验证。
问题是在 SetName
与 bobby
成功完成后,它 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"。我认为这不是故意的。