C#-在何处执行验证
我有一个关于何时验证C#表单应用程序上的输入的问题 从表单应用程序获取输入时,可以在解析主表单类中文本字段的数据时运行所有验证,然后在任何地方使用。例如: 方法1:C#-在何处执行验证,c#,validation,oop,object,stack,C#,Validation,Oop,Object,Stack,我有一个关于何时验证C#表单应用程序上的输入的问题 从表单应用程序获取输入时,可以在解析主表单类中文本字段的数据时运行所有验证,然后在任何地方使用。例如: 方法1: class Car { private string registration { set; get; } // NO VALIDATION HERE } // in the form class private void add_Click(object sender, EventArgs e) { // get
class Car
{
private string registration { set; get; } // NO VALIDATION HERE
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
int reg_valid = Validate.registration(txtReg.Text); // VALIDATION IS DONE HERE
if(reg_valid)
{
Car.registration = txtReg.Text;
} else {
// Registration invalid - throw error
}
}
class Car
{
// out registration
private string registration;
// we can set our registration here and return false if there is an error
bool set_registration(registration)
{
int reg_valid = Validate.registration(registration); // VALIDATION IS DONE HERE
if(reg_valid) {
this.registration = registration;
} else {
return false; // if error
}
return true; // if all goes well
}
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
string registration = txtReg.Text; // NO VALIDATION DONE HERE
// we can then store this in our object
if( ! Car.set_registration(registration))
{
// Registration invalid - throw error
}
}
在实际的Car对象中不会进行验证,因为所有验证都是在form类中完成的
另一种方法是在实际的类中验证输入,它存储在类似的类中:
方法2:
class Car
{
private string registration { set; get; } // NO VALIDATION HERE
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
int reg_valid = Validate.registration(txtReg.Text); // VALIDATION IS DONE HERE
if(reg_valid)
{
Car.registration = txtReg.Text;
} else {
// Registration invalid - throw error
}
}
class Car
{
// out registration
private string registration;
// we can set our registration here and return false if there is an error
bool set_registration(registration)
{
int reg_valid = Validate.registration(registration); // VALIDATION IS DONE HERE
if(reg_valid) {
this.registration = registration;
} else {
return false; // if error
}
return true; // if all goes well
}
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
string registration = txtReg.Text; // NO VALIDATION DONE HERE
// we can then store this in our object
if( ! Car.set_registration(registration))
{
// Registration invalid - throw error
}
}
方法1看起来更干净,但是我们使用私有属性的原因之一是为了验证任何解析参数,这就是为什么方法2看起来是更好的选择。此外,使用方法2,错误必须在堆栈中执行多次,这会导致重复的if语句
*请注意,此代码尚未运行,因此可能包含错误。您应该拥有类的核心,以及与用户界面相关的类。首先,创建应用程序的核心类(业务逻辑)。当然,您应该在这里进行验证。实际上,编写代码时,您似乎不知道谁将实现用户界面。此外,还要考虑到用户界面可以更改,而核心类应该保持不变 在编写用户界面时,您会意识到,如果不进行任何验证,当用户输入一些数据案例时,将引发异常。这将使您也在用户界面类中创建验证
因此,答案是,您最终将对应用程序的两个部分进行验证。您将对私有成员使用公共属性,在属性内进行检查,然后将其分配给类成员
class Car
{
private string registration;
public string Registration
{
get { return registration;}
set {
if(Validate.registration(value))
registration = value;
else
throw new Exception("Your exception message here");
}
}
}
private void add_Click(object sender, EventArgs e)
{
Car.Registration = txtReg.Text;
}
有两种验证:
- 数据类型/属性限制/解析李>
- 逻辑(属性之间的值)李>
属性网格
。如果您的属性接受值或抛出:
class Car
{
private int _someValue;
public int SomeValue
{
get { return _someValue; }
set
{
if(value > 100)
throw new OutOfRangeException(...);
_someValue = value;
}
}
}
这确保了Car
可以验证自己的属性,而不管它们是如何设置的(反序列化、PropertyGrid
、直接属性值、反射等)
另一件事是一些逻辑验证,它不能在实例级别执行,或者您根本不关心它(让实例在没有异常的情况下创建)。这一个必须放入编辑器代码(用于创建实例的形式)
至于我自己,谈到TextBox
,我更喜欢定制MyTextBox
控件,它具有所有与解析相关的验证(方法GetDouble()
,GetInt()
,GetIntTime()
,等等)以及设置/查询它的可能性(属性IsDouble
,IsInt
,等等)
注意:基于意见的答案!
这取决于项目的要求、规模、时间(以及许多其他重要因素,如“用户友好应用程序”或不重要的因素,如“我自己的品味是……”
由于每个人的可能病例范围很广,因此答案不能用满足每个人需求的一般指南来表达
您的问题涉及两个要操纵的对象:
- 一种用作用户界面的表单,用户可以在其中输入任何内容(假设由“用户输入*任何*值,然后单击按钮”定义)
- 当值(Setter)有效时提供给它的类属性
- 你没有时间,需求只是告诉你“输入一个值”,这是一个项目中的一个小任务,在这个按钮中使用的一个小类上没有重要意义,你很懒: =>在按钮单击中,使用一个或两个禁止的检查进行严格验证,这些检查会弹出任何不允许的值,并根据错误的性质显示消息框。仅将值传递给类,并在具有有效值时进一步传递
- 你没有时间,简单的要求,小任务不重要,但主要使用的是课程,但你很懒: =>将验证移到类中的上方,然后抛出一个、两个或三个带有自定义消息的通用异常。在使用该类的任何UI操作中,使用Try/Catch在按钮中捕获异常单击并显示MessageBox,在捕获异常的情况下不进行进一步操作
- 你有5分钟,简单的要求,小的非关键任务,重要的班级角色: =>如前所述,决定是否推荐另一种显示用户的方式(取决于您的目标用户),例如在单击按钮后更改文本框的背景色,在标签中显示消息,而不是用对话框烦扰用户
- 你有10分钟,简单的要求,重复的任务,重要的班级角色:
=>找到一种快速测试给定值的方法,并在类中创建一个public或friend(static?)函数,该函数返回验证尝试的结果,如可能的验证错误的枚举(*参见下面的编辑):
a)uicarvalidationnum.Valid
b).TooLong
c).NullValue
d)禁止字符
e) …
然后,您可以在类内部和外部使用该验证函数。这样,在执行Setter和之前,您可以处理无效的Setter尝试 public registrationValidation_Enum test_registration( string newRegistration) { registrationValidation_Enum checkResult = registrationValidation_Enum.Valid; // Do the checks here if (newRegistration.Length > 10) { checkResult = checkResult | registrationValidation_Enum.TooLong; } if (containsNonAlphNumericChars(newRegistration)) { checkResult = checkResult | registrationValidation_Enum.InvalidChars; } // ... return checkResult; }
// this bypass the double check : attempts to set the value if Valid. // otherwise, either returns a validation result, // either throws an exception. public registrationValidation_Enum validate_registration( string newRegistration, bool canThrowException) { bool isValid = test_registration(newRegistration); if (isValid == registrationValidation_Enum.Valid) { registration = newRegistration; return registrationValidation_Enum.Valid; } else { if (canThrowException) { string exceptionMessage = ""; if (isValid | registrationValidation_Enum.TooLong) { exceptionMessage += "Registration too long" + Environment.NewLine; } if (isValid | registrationValidation_Enum.InvalidChars) { exceptionMessage += "Registration contains invalid characters" + Environment.NewLine; } // .... Throw New Exception(exceptionMessage); } else { return isValid; } } }