簡體   English   中英

驗證構造函數參數的正確方法是什么

[英]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”,但在這種情況下,我寧願只是阻止一個無效的名稱,然后嘗試假設一些替代行為。

  1. 拋出ArgumentNullException
  2. 如果namenull ,則記錄ctor拋出ArgumentNullException
  3. 如果您使用的是代碼約定 ,請在參數驗證后添加Contract.EndContractBlock()行。

編輯:而不是這個:

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

用這個:

if (string.IsNullOrEmpty(name))

這里的首選解決方案是拋出異常。 早退,經常失敗。 記錄構造函數的有效參數,並在無效參數上拋出ArgumentNullExceptionArgumentOutOfRangeException

在我看來,重點是你不想默默地吸收失敗。 假設用戶輸入的名稱不正確(例如,意外地將其保留為空)。 最好讓操作失敗並向用戶返回通知而不是吞下失敗(例如,默認)並讓用戶不知道他們錯誤輸入了他們的條目。

我回答了一些類似的問題,以便與一些同事解決爭執。

“但是一旦調用了構造函數,就會創建對象的實例,無論它是否傳遞了有效的參數。”

僅當構造函數正常返回時,才會創建對象(即非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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM