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

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

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

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

如下所示抛出exception最好的方法? 或者是否有其他方法更受欢迎?

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

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

  1. 抛出ArgumentNullException
  2. 如果namenull ,则记录ctor抛出ArgumentNullException
  3. 如果您使用代码约定 ,请在参数validation后添加Contract.EndContractBlock()行。

编辑:而不是这个:

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

用这个:

 if (string.IsNullOrEmpty(name)) 

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

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

我回答了一些类似的问题,以便与一些同事解决争执。

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

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

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

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

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

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

这个类在这里可以使用System; 使用System.Globalization;

  namespace Microsoft.Practices.Mobile.CompositeUI.Utility { ///  /// Common guard clauses. ///  public static class Guard { ///  /// Checks a string argument to ensure it isn't null or empty. ///  /// The argument value to check. /// The name of the argument. 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)); } ///  /// Checks an argument to ensure it isn't null. ///  /// The argument value to check. /// The name of the argument. public static void ArgumentNotNull(object argumentValue, string argumentName) { if (argumentValue == null) throw new ArgumentNullException(argumentName); } ///  /// Checks an Enum argument to ensure that its value is defined by the specified Enum type. ///  /// The Enum type the value should correspond to. /// The value to check for. /// The name of the argument holding the value. 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())); } ///  /// Verifies that an argument type is assignable from the provided type (meaning /// interfaces are implemented, or classes exist in the base class hierarchy). ///  /// The argument type. /// The type it must be assignable from. /// The argument name. 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); } } }