我打算创建一个 ErrorMessages 类,其中包含一个可以放置所有 errorMessages 的列表。每次给出无效输入时,都会将一条新消息添加到 errorMessages 列表中。因此,如果用户单击“创建”按钮,则会显示列表中的所有消息。这是处理事情的好方法吗?
主观上,我认为最好提供用户输入的值无效的即时反馈。这样,他们可以立即返回并修复它。
我想说的是,考虑一下。你提出的方法最终会给他们一个巨大的问题列表,这不是很用户友好。此外,他们将如何记住所有这些问题以便能够一次又一次地修复它们?(提示:他们不是。)
相反,我建议使用ErrorProvider
该类在适当的控件旁边显示任何错误。我在这里和这里的回答中更多地谈到了这种方法。
当然,您仍然需要确保在最终提交时(单击 OK/Submit 按钮)所有输入都是有效的,但这只是检查是否存在任何错误的简单案例。
我可以在 Form 类中轻松做到这一点。但我记得一些验证设置属性中输入的最佳实践方法。
是的,这里的想法是封装。Form 类应该只知道表单的东西。不应该要求知道哪种输入对所有不同的控件都有效/无效。
相反,这个验证逻辑应该放在其他地方,例如存储数据的类中。该类将公开公共属性以获取和设置数据,并且在 setter 方法内部,它将验证数据。
这意味着您的 Form 所要做的就是在您的数据类上调用一个 setter 方法。表单不需要知道如何验证数据,甚至不需要知道数据的含义,因为数据类处理所有这些。
这不应该发生,除非输入有效,否则不能创建类的实例。
如果确实如此,您将需要为类提供一个构造函数,该构造函数接受它需要的所有数据作为参数。然后构造函数的主体将验证指定的数据并在其中任何一个无效时抛出异常。该异常将阻止创建类,确保不存在包含无效数据的类的实例。
这样的类可能根本没有 setter 方法——只有 getter。
然而,这在 C# 世界中是一种不寻常的要求(尽管它在 C++ 中可能很常见)。通常,将验证代码放在 setter 中就可以了。
我的财产有一些私人二传手。所以它们只能在我的数据类的构造函数中设置。现在的问题是,这似乎使我的验证并不容易
为什么这会改变什么?您仍然在私有 setter 内部处理验证。如果验证失败,则抛出异常。因为构造函数不处理异常,它继续从该方法冒泡到试图实例化对象的代码。如果该代码想要处理异常(例如,向用户显示错误消息),它可以这样做。
当然,在输入无效的情况下抛出异常不一定是“最佳实践”。原因是通常应该为意外情况保留异常,并且用户搞砸并向您提供无效数据是可以预料的。然而:
- 这是您在构造函数内部进行数据验证的唯一选项,因为构造函数不能返回值。
- 在 UI 代码中,异常处理的成本基本上可以忽略不计,因为现代计算机处理异常的速度比用户感知屏幕变化的速度要快。