C# 验证构造函数数据

C# 验证构造函数数据,c#,class-design,structure,C#,Class Design,Structure,“C#类设计手册”(第137页)中的示例类没有从仅类构造函数内部调用特定字段的类验证方法。因此,基本上,示例类允许您创建一个包含错误数据的对象,并且只在调用字段的属性时抛出该数据的错误,该属性随后对其进行验证。所以你现在有一个坏东西,直到事后才知道 我一直不明白为什么他们不直接从构造函数调用属性,从而在初始化过程中发现错误数据时立即抛出错误?我给他们发了电子邮件,但没有用 我倾向于通过从构造函数调用我的属性来使用以下格式-这是验证初始化数据的正确结构吗?泰 class Foo { pri

“C#类设计手册”(第137页)中的示例类没有从仅类构造函数内部调用特定字段的类验证方法。因此,基本上,示例类允许您创建一个包含错误数据的对象,并且只在调用字段的属性时抛出该数据的错误,该属性随后对其进行验证。所以你现在有一个坏东西,直到事后才知道

我一直不明白为什么他们不直接从构造函数调用属性,从而在初始化过程中发现错误数据时立即抛出错误?我给他们发了电子邮件,但没有用

我倾向于通过从构造函数调用我的属性来使用以下格式-这是验证初始化数据的正确结构吗?泰

class Foo
{
    private string _emailAddress;

    public Foo(string emailAddress)
    {
        EmailAddress = emailAddress;
    }

    public string EmailAddress
    {
        get { return _emailAddress; }
        set
        {
            if (!ValidEmail(value))
                throw new ArgumentException
                    (string.Format
                    ("Email address {0} is in wrong format", 
                    value));

            _emailAddress = value;
        }
    }


    private static bool ValidEmail(string emailAddress)
    {
        return Regex.IsMatch
            (emailAddress, @"\b[A-Z0-9._%+-]+" +
                           @"@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
                           RegexOptions.IgnoreCase);
    }
}

首先,您可能会遇到可怕的NullReferenceException,因为您没有检查emailAddress在任何级别是否为null。该特定检查应该在构造函数本身中完成,如果emailAddress为null,则抛出ArgumentNullException。至于其余的,我看不出它有什么特别的问题,因为它写在您的示例中。但是,如果将属性设置为虚拟,并从此类派生子类,则可能会出现一些问题。字段初始化、基类和派生类constructor的执行顺序就成了一个问题,您必须小心。

我认为这种方法没有错。您可以在构造函数中对此调用方法,而属性setter/getter只是方法调用的语法糖。

是的,如果您的一般方法是:

确保只能获取
有效的
对象的实例

那我就喜欢了


构造函数应该用来创建立即有效的对象,而不仅仅是为要放入的东西创建一个“容器”。

设置电子邮件地址时,将进行验证。这是您想要的位置,因为稍后可能会再次设置电子邮件地址


如果您也在构造函数中调用了验证,那么您将进行额外的、冗余的验证调用(在构造时调用一次,在构造函数中设置电子邮件地址时调用另一次)。

不在构造函数中验证数据对我来说毫无意义。正如您所指出的,对象可能最终处于无效状态。考虑到这种设计,您甚至不会意识到在调用getter时有坏数据

对于任何中等或更高复杂性的问题,我倾向于使用打破规则的方法,而不是立即抛出异常。在这种方法中,我定义了一个BrokerRules对象,该对象包含关于无效的类和属性以及无效原因的信息。然后,在一个公共基类中,我定义了一个列表来保存关于对象的所有“错误”的列表。属性(同样在基类中)IsValid指示当前是否存在任何损坏的规则


这样做的好处是,对象状态可能存在一些潜在的问题。如果要求用户更正问题(即,此对象是从UI设置的),提供所有问题的列表可以让用户一次性更正问题,而不是修复一个错误,然后被告知还有另一个错误。还有一个。等等。

是的,这里的想法是只获取有效对象——我添加了构造函数的重载,允许用户输入一个空白字段,这样做是可以的。如果电子邮件地址是在构造函数中设置的,则类的行为与通过属性设置器设置的不同。不一致的行为不是一个好的设计属性:-)在示例代码中,根据我所知,asker提供的构造函数使用了属性setter,因此该行为实际上是一致的。有什么我不知道的吗?嗯?电子邮件地址的原始设置在调用_emails属性的构造函数中。如果我直接设置电子邮件,那么如果传入了一封坏电子邮件,我就会有一个坏对象。只有在对象实例化后更改了属性时,才会验证它。构造函数正在调用属性的setter:“EmailAddress”是的,我理解-我编写了它。我不明白的是你的评论。。。对不起,我想你没有抓住我问题的重点。书中的示例只是直接设置字段,不进行任何验证,但在创建对象后访问属性时验证字段并抛出错误…顺便说一句。。。当我说直接设置字段时,我的意思是在构造函数中。这可能应该是一个公共问题-如果可以,请有人正确设置它。谢谢Eric-我将研究打破规则的方法!刚开始构建框架,还在学习。学习了“框架设计指南”,我对它非常感兴趣!好书。