Как правильно проверить аргументы конструктора - PullRequest
5 голосов
/ 21 июля 2009

Итак, у меня есть класс с одним строковым параметром в его конструкторе:

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

но я никогда не хочу беспокоиться о том, чтобы кто-то инициализировал экземпляр MyClass именем NULL или строкой нулевой длины. Что лучше всего было проверить параметр? Со свойством или методом вы всегда можете просто ничего не делать, возвращать ноль или не устанавливать ничего, если указан неверный аргумент. Но после вызова конструктора экземпляр объекта уже создан независимо от того, были ли переданы допустимые аргументы.

Является ли исключение, как показано ниже, лучшим способом? Или есть какой-то другой способ, который более предпочтителен?

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

    this.Name = name;
}

Конечно, я всегда мог бы установить имя на какое-то значение по умолчанию, например «Безымянный MyClass», если аргумент недействителен, но в этом случае я бы предпочел просто предотвратить недопустимое имя, а затем попытаться принять какое-то альтернативное поведение.

Ответы [ 5 ]

7 голосов
/ 21 июля 2009
  1. Брось ArgumentNullException
  2. Документ, который бросает ctor ArgumentNullException, если name равно null
  3. Если вы используете Кодовые контракты , добавьте строку Contract.EndContractBlock () после проверки параметров.

Редактировать: Вместо этого:

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

Используйте это:

if (string.IsNullOrEmpty(name))
3 голосов
/ 21 июля 2009

Предпочтительным решением здесь является исключение. Ошибка рано, часто неудача. Документируйте, какие допустимые параметры есть для вашего конструктора и что он выдает ArgumentNullException или ArgumentOutOfRangeException для недопустимых параметров.

На мой взгляд, существенным моментом является то, что вы не хотите молча поглощать неудачи. Предположим, что пользователь ввел имя неправильно (например, случайно оставил его пустым). Лучше сделать операцию неудачной и вернуть пользователю уведомление, чем проглотить ошибку (скажем, по умолчанию) и не дать пользователю не знать, что он неправильно набрал свою запись.

Я задал похожий вопрос некоторое время назад, чтобы уладить спор с некоторыми коллегами.

"Но как только конструктор вызван, экземпляр объекта уже создан независимо от того, были ли переданы допустимые аргументы."

Объект создается (т. Е. Не ноль), только если конструктор возвращает нормально.

1 голос
/ 21 июля 2009

Существует служебный класс Guard, который может оказаться полезным для проверки аргументов, передаваемых любому методу.

Класс доступен здесь используя Систему; используя 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);
        }
    }
}
1 голос
/ 21 июля 2009

Если передача пустого или нулевого имени представляет ошибку, разумно сделать исключение. Игнорирование нулевого имени и выполнение произвольного восстановления просто маскирует ошибку и может привести к неверному состоянию.

Если передача имени не является допустимым способом создания объекта, предложите конструктор без параметров.

1 голос
/ 21 июля 2009

Вы можете либо установить имя по умолчанию, либо выдать исключение. Все остальное просто неправильно, так как это создаст объект с недопустимым состоянием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...