基本用户输入字符串验证
本文关键字:字符串 验证 输入 用户 | 更新日期: 2023-09-27 18:10:02
我一直在我的person抽象类的name属性中写一个检查。我遇到的问题是,我正试图实现一段代码,它不允许用户将字段留空或超过名称限制35个字符或输入一个数字,但我坚持了下来。如果有人能帮助或建议我。
public string Name
{
get { return name; }
set
{
while (true)
{
if (value == "" || value.Length > 35)
{
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
continue;
}
foreach (char item in value)
{
if (char.IsDigit(item))
{
Console.Write("Digits Are NotAllowed....'n");
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
break;
}
}
break;
}
name = value;
}
}
不要在属性中执行任何形式的UI或I/O。
public string Name
{
get { return _name; }
set
{
if (! Regex.IsMatch(value, @"'w{1-35}"))
throw new ArgumentException("Name must be 1-35 alfanum");
_name = value;
}
}
确切的正则表达式有待讨论,但最佳实践是:
- 不要试图列出并拒绝所有你不喜欢的模式。可能性太大了
- 接受你的期望(和理解(,拒绝其他一切
这种验证应该被分解。setter应该只知道它所具有的各种限制,并在无效值使其达到这种程度的情况下抛出异常不要将用户界面代码放在那里。
试试这样的东西:
public string Name
{
get { return name; }
set
{
if (value == "" || value.Length > 35)
{
throw new ArgumentException("Invalid name length.");
}
foreach (char item in value)
{
if (char.IsDigit(item))
{
throw new ArgumentException("Digits are not allowed.");
}
}
name = value;
}
}
然后在你的控制台应用程序中这样做:
bool success = false;
while(!success)
{
try
{
Console.WriteLine("Please enter a name:");
myObject.Name = Console.ReadLine();
success = true;
}
catch(ArgumentException ex)
{
Console.WriteLine(ex.Message);
}
}
首先,不要在setter中要求Console输入。这是一种严重的不良做法。相反,您应该从setter抛出一个Exception,并让调用者根据需要进行处理:
public string Name
{
get { return name; }
set
{
if(String.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name must have a value");
if(value.Length > 35)
throw new ArgumentException("Name cannot be longer than 35 characters");
if(value.Any(c => char.IsDigit(c))
throw new ArgumentException("Name cannot contain numbers");
name = value;
}
}
然后,您可以在调用代码中适当地捕捉和处理异常(在您的情况下,这将涉及重新提示用户输入(。
根据规则处理此问题的解决方案几乎是显而易见的,但问题是,最好不要将检查和验证逻辑放在属性的setter方法中,例如,您可以有一个单独的类,该类为您承担验证责任,您可以告诉它这样做,然后适当地使用结果。在这种情况下,你遵循"告诉,不要问"规则和"单一责任原则">
好运
public string Name
{
get { return name; }
set { name = value; }
}
public static bool IsNameValid(string name)
{
if (string.IsNullOrEmpty(name) || name.Length > 35)
{
return false;
}
foreach (char item in value)
{
if (!char.IsLetter(item))
{
return false;
}
}
return true;
}
最后是用于读取用户输入的代码片段。
var yourClassInstance = new YourClass();
string input
bool inputRead = false;
while(!inputRead)
{
var input = Console.ReadLine();
inputRead = YourClass.IsNameValid(input);
}
yourClassInstance.Name = inputRead;
简单的答案是在值无效时循环:
public string GetName()
{
String name = String.Null;
do
{
Console.Write("Please Enter Correct Name: ");
name = Console.ReadLine();
} while (!ValidateName(name))
}
public bool ValidateName(string name)
{
//String validation routine
}
话虽如此,我相信你会从其他答案中看到,改变名字的给出位置。一般来说,访问者实际上只是为了快速"获取"answers"设置"类中的内容。
我将创建一个方法来更改包含验证逻辑的名称。如果您想检查名称是否有效,因此不必处理argumentexception。请先进行检查,在调用ChangeName 之前调用IsValidName
public class Person
{
public void ChangeName(string name)
{
if (!IsValidName(name))
{
throw new ArgumentException(....);
}
else
this.Name = value;
}
public bool IsValidName(string name)
{
// is the name valid using
}
public string Name { get; private set; }
}
使用
var newName = Console.ReadLine();
var person = new Person();
while (!person.IsValidName(newName))
{
newName = Console.ReadLine();
}
person.ChangeName(newName);
从语义的角度来看,setter顾名思义,就是setter!它应该用于设置类的私有/受保护字段从可测试性的角度来看,你的设计很难被自动测试,更不用说不可能!
这让我想起了我以前编写的一段代码,其中setter打开一个套接字并通过网络发送内容!代码应该做它读到的事情,想象一下,如果有人使用你的代码,调用你的setter,并想知道他/她的应用程序到底为什么挂起(等待用户输入(
我认为代码可读性和可测试性更强的方法是拥有一个验证器类,确保用户以正确的格式输入正确的数据。验证器应该将输入流作为数据源,这将帮助您轻松测试它
问候,
除了Skeet先生所说的,似乎你应该用continue
替换这个break
,以验证新值(就像你在第一次长度检查中所做的那样(:
if (char.IsDigit(item))
{
Console.Write("Digits Are NotAllowed....'n");
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
continue; //here
}