[英]What is the correct way to validate the arguments of a 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”,但在這種情況下,我寧願只是阻止一個無效的名稱,然后嘗試假設一些替代行為。
ArgumentNullException
null
,則記錄ctor拋出ArgumentNullException
編輯:而不是這個:
if (name == null || name == "")
用這個:
if (string.IsNullOrEmpty(name))
這里的首選解決方案是拋出異常。 早退,經常失敗。 記錄構造函數的有效參數,並在無效參數上拋出ArgumentNullException
或ArgumentOutOfRangeException
。
在我看來,重點是你不想默默地吸收失敗。 假設用戶輸入的名稱不正確(例如,意外地將其保留為空)。 最好讓操作失敗並向用戶返回通知而不是吞下失敗(例如,默認)並讓用戶不知道他們錯誤輸入了他們的條目。
我回答了一些類似的問題,以便與一些同事解決爭執。
“但是一旦調用了構造函數,就會創建對象的實例,無論它是否傳遞了有效的參數。”
僅當構造函數正常返回時,才會創建對象(即非null)。
您可以將名稱設置為某個默認值或拋出異常。 其他任何東西都是完全錯誤的,因為它會創建一個具有無效狀態的對象。
如果傳遞空名或空名表示錯誤,則拋出異常是合理的。 忽略空名稱並執行一些任意恢復只是掩蓋錯誤並可能導致無效狀態。
如果不傳遞名稱是構造對象的有效方法,則提供無參數構造函數。
有一個Guard實用程序類,您可能會發現它可用於驗證傳遞給任何方法的參數。
這個類在這里可以使用System; 使用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);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.