Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-在何处执行验证_C#_Validation_Oop_Object_Stack - Fatal编程技术网

C#-在何处执行验证

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

我有一个关于何时验证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 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;
                }
            }
        }