验证构造函数参数的正确方法是什么

时间:2009-07-21 03:20:46

标签: c# validation constructor

所以我的构造函数中有一个带有单个字符串参数的类:

public MyClass(string name)
{
    this.Name = name;
}

但我永远不想担心有人初始化一个名为NULL或零长度字符串的MyClass实例。什么是最好的验证参数?使用属性或方法,如果提供了无效参数,您可以随时执行任何操作,返回null或不设置任何内容。但是一旦调用了构造函数,就会创建该对象的实例,无论它是否传递了有效的参数。

如下图所示抛出异常的最佳方式?或者是否有其他更优选的方法?

public MyClass(string name)
{
    if (name == null | name == "") throw new ArgumentException("Name can not be null or blank", "name");

    this.Name = name;
}

当然,如果参数无效,我总是可以将名称设置为某些默认值,例如“Unnamed MyClass”,但在这种情况下,我宁愿只是阻止一个无效的名称,然后尝试假设一些替代行为。

5 个答案:

答案 0 :(得分:7)

  1. 抛出ArgumentNullException
  2. 如果名称ArgumentNullException
  3. ,则ctor抛出null的文件
  4. 如果您使用Code Contracts,请在参数验证后添加Contract.EndContractBlock()行。
  5. 编辑:而不是:

    if (name == null || name == "")
    

    使用此:

    if (string.IsNullOrEmpty(name))
    

答案 1 :(得分:3)

这里的首选解决方案是抛出异常。早退,经常失败。记录构造函数的有效参数,并在无效参数上引发ArgumentNullExceptionArgumentOutOfRangeException

在我看来,重点是你不想默默地吸收失败。假设用户输入的名称不正确(例如,意外地将其保留为空)。最好让操作失败并向用户返回通知,而不是吞下失败(例如,默认)并让用户不知道他们错误输入了他们的条目。

我回答了类似question一段时间,以便与一些同事解决争执。

“但是一旦调用了构造函数,就会创建该对象的实例,无论它是否传递了有效的参数。”

仅当构造函数正常返回时才创建对象(即非null)。

答案 2 :(得分:1)

您可以将名称设置为某个默认值或抛出异常。其他任何东西都是完全错误的,因为它会创建一个具有无效状态的对象。

答案 3 :(得分:1)

如果传递空名或空名表示错误,抛出异常是合理的。忽略空名称并执行一些任意恢复只是掩盖错误并可能导致无效状态。

如果不传递名称是构造对象的有效方法,则提供无参数构造函数。

答案 4 :(得分:1)

有一个Guard实用程序类,您可能会发现它可用于验证传递给任何方法的参数。

该课程是可用的here     使用系统;     使用System.Globalization;

    namespace Microsoft.Practices.Mobile.CompositeUI.Utility
    {
        /// <summary>
        /// Common guard clauses.
        /// </summary>
        public static class Guard
        {


    /// <summary>
        /// Checks a string argument to ensure it isn't null or empty.
        /// </summary>
        /// <param name="argumentValue">The argument value to check.</param>
        /// <param name="argumentName">The name of the argument.</param>
        public static void ArgumentNotNullOrEmptyString(string argumentValue, string argumentName)
        {
            ArgumentNotNull(argumentValue, argumentName);

            if (argumentValue.Trim().Length == 0)
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.StringCannotBeEmpty, argumentName));
        }

        /// <summary>
        /// Checks an argument to ensure it isn't null.
        /// </summary>
        /// <param name="argumentValue">The argument value to check.</param>
        /// <param name="argumentName">The name of the argument.</param>
        public static void ArgumentNotNull(object argumentValue, string argumentName)
        {
            if (argumentValue == null)
                throw new ArgumentNullException(argumentName);
        }

        /// <summary>
        /// Checks an Enum argument to ensure that its value is defined by the specified Enum type.
        /// </summary>
        /// <param name="enumType">The Enum type the value should correspond to.</param>
        /// <param name="value">The value to check for.</param>
        /// <param name="argumentName">The name of the argument holding the value.</param>
        public static void EnumValueIsDefined(Type enumType, object value, string argumentName)
        {
            if (Enum.IsDefined(enumType, value) == false)
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                    Properties.Resources.InvalidEnumValue,
                    argumentName, enumType.ToString()));
        }

        /// <summary>
        /// Verifies that an argument type is assignable from the provided type (meaning
        /// interfaces are implemented, or classes exist in the base class hierarchy).
        /// </summary>
        /// <param name="assignee">The argument type.</param>
        /// <param name="providedType">The type it must be assignable from.</param>
        /// <param name="argumentName">The argument name.</param>
        public static void TypeIsAssignableFromType(Type assignee, Type providedType, string argumentName)
        {
            if (!providedType.IsAssignableFrom(assignee))
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
                    Properties.Resources.TypeNotCompatible, assignee, providedType), argumentName);
        }
    }
}