Проверить данные конструктора - PullRequest
3 голосов
/ 27 августа 2009

Образец класса в «C # Class Desing Handbook» (стр. 137) не вызывает метод проверки классов для определенного поля из конструктора «Только классы». Таким образом, в основном образец класса позволяет вам создать объект с неверными данными и выдает ошибку для этих данных только тогда, когда вы вызываете свойство поля, которое затем проверяет его. Итак, у вас теперь есть плохой объект, и вы об этом не узнаете, пока не закончите.

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

Я склонен использовать следующий формат, вызывая мои свойства из моих конструкторов - это правильная структура для проверки данных инициализации? ти

class Foo
{
    private string _emailAddress;

    public Foo(string emailAddress)
    {
        EmailAddress = emailAddress;
    }

    public string EmailAddress
    {
        get { return _emailAddress; }
        set
        {
            if (!ValidEmail(value))
                throw new ArgumentException
                    (string.Format
                    ("Email address {0} is in wrong format", 
                    value));

            _emailAddress = value;
        }
    }


    private static bool ValidEmail(string emailAddress)
    {
        return Regex.IsMatch
            (emailAddress, @"\b[A-Z0-9._%+-]+" +
                           @"@[A-Z0-9.-]+\.[A-Z]{2,4}\b",
                           RegexOptions.IgnoreCase);
    }
}

Ответы [ 5 ]

2 голосов
/ 27 августа 2009

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

Для чего-либо среднего уровня сложности или выше, я склонен использовать подход «нарушенные правила», а не сразу выбрасывать исключение. В этом подходе я определяю объект BrokenRules, который содержит информацию о недопустимом классе и свойстве, а также причину его недопустимости. Затем в общем базовом классе я определяю список для хранения списка всего «неправильного» об объекте. Свойство (снова в базовом классе) IsValid указывает, существуют ли в настоящее время какие-либо нарушенные правила.

Преимущество этого в том, что в состоянии объекта может быть несколько неправильных вещей. Если пользователя просят исправить проблемы (т. Е. Этот объект устанавливается из пользовательского интерфейса), предоставление списка всех проблем позволяет пользователю исправить их за один раз, вместо того, чтобы исправлять одну ошибку, просто чтобы узнать, что есть другая. И еще один. И т.д.

2 голосов
/ 27 августа 2009

Да, если ваш общий подход:

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

тогда мне это нравится.

Конструкторы следует использовать для создания объектов, которые будут действительны немедленно, а не для создания просто «контейнера» для вещей, которые нужно вставить.

2 голосов
/ 27 августа 2009

Ну, во-первых, вы, вероятно, получите страшное исключение NullReferenceException, так как вы не проверяете, является ли emailAddress нулевым на любом уровне. Эта конкретная проверка должна быть сделана в самом конструкторе, и если emailAddress имеет значение null, генерировать исключение ArgumentNullException. В остальном я не вижу особых проблем с ним, как написано в вашем примере. Однако есть некоторые проблемы, которые могут возникнуть, если вы сделаете свойство виртуальным и получите потомков из этого класса. Порядок выполнения инициализации поля, констант базового и производного классов становится проблемой, и вы должны быть осторожны.

0 голосов
/ 27 августа 2009

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

Если бы вы также вызывали валидацию в конструкторе, вы бы делали дополнительный избыточный вызов валидации (один раз при создании, другой - при установке адреса электронной почты в конструкторе).

0 голосов
/ 27 августа 2009

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

...