Проблемы с пользовательскими исключениями в C # Windows Forms

#c# #custom-exceptions

#c# #пользовательские исключения

Вопрос:

Я пытаюсь заставить это генерировать исключение, если year введен в TextBoxCopyrightYear.Текст выше текущего года, но, похоже, он этого не делает.

Вопрос в том… почему он не выдает исключение, когда я ввожу что-то выше 2011?

Я создал пользовательский класс исключений CopyrightYearOutOfRange:

 public class CopyrightYearOutOfRange : Exception
{
    private LibraryBook book;
    private int year;

    public CopyrightYearOutOfRange(LibraryBook book, int year)
        : base("Year is beyond current year. This is impossible.")
    {
        this.book = book;
        this.year = year;
    }

    public LibraryBook Book { get { return book; } }
    public int Year { get { return year; } }

    public CopyrightYearOutOfRange(string message)
        : base(message)
    { 
    }
}
  

И это выдается в этом разделе в моем классе LibraryBook следующим образом:

 public LibraryBook(string title, string author, int copyrightYear)
{
    Title = title;
    Author = author;
    if (isValidYear(copyrightYear))
    {
        CopyrightYear = copyrightYear;
    }
    else
    {
        throw new CopyrightYearOutOfRange(this, copyrightYear);
    }
}

private bool isValidYear(int year)
{
    return year <= 2011;
}
  

Итак, я создал этот код, чтобы проверить, действителен ли пользовательский ввод…

 // makes sure data is valid...
private bool validateData()
{
    int year;
    int errorCount = 0;
    string errorHeader = "";
    string errorMessage = "";
    string errorTitle = "";
    string plural = "";

    if (textBoxTitle.Text.Length == 0)
    {
        errorMessage  = "nEnter a title";
        errorCount  ;
    }

    if (!int.TryParse(textBoxCopyrightYear.Text, out year) || year < 1)
    {
        errorMessage  = "nEnter year as a positive number";
        errorCount  ;
    }
    else
    {
        try
        {
            // Is this where I'm making a mistake?
            int.TryParse(textBoxCopyrightYear.Text, out year);
        }
        catch (CopyrightYearOutOfRange ex)
        {
            MessageBox.Show(
                string.Format("{0}", ex.Message)
                , "Copyright out of range exception"
                , MessageBoxButtons.OK
                , MessageBoxIcon.Exclamation
                );
        }
    }
  

и вот код кнопки ok:

 private void buttonOK_Click(object sender, EventArgs e)
{
    if (validateData())
    {
        controlsToObject();
        this.DialogResult = DialogResult.OK;
    }
}
  

Редактировать:
Вот код, который создает объект. Это то место, куда я должен поместить блок try catch?

     private void controlsToObject()
    {
        if (libraryBook == null)
        {
            libraryBook = new LibraryBook();
        }

        libraryBook.Title = textBoxTitle.Text;
        libraryBook.Author = textBoxAuthor.Text;
        libraryBook.CopyrightYear = int.Parse(textBoxCopyrightYear.Text);
    }
  

СНОВА:
Вопрос в том… почему он не выдает исключение, когда я ввожу что-то выше 2011?

Комментарии:

1. Вы создаете исключение в конструкторе LibraryBook, но где именно создаются объекты этого класса? Я не вижу этого в коде…

Ответ №1:

Ну, исключение выдается из конструктора LibraryBook класса — но вы нигде его не вызываете. Вы преобразуете номер года из string в int. Нет причин для возникновения исключения там.

Ответ №2:

Решением для вас является создание объекта LibraryBook из вашего блока try, чтобы данные были проверены в конструкторе.

добавьте это в свою попытку:

 var b = new LibraryBook(textBoxTitle.Text, textBoxAuthor.Text, int.Parse(textBoxCopyrightYear.Text));
  

Комментарии:

1. Спасибо вам за это. Я понимаю, что это создает объект LibraryBook. Но правильно ли указано местоположение моего блока try-catch? Или это должно быть в правке в сообщении?

2. Видите ли, ваша логика проверки находится в двух разных местах. В конструкторе LibraryBook и в функции validateData. Было бы разумнее, если бы вся ваша логика проверки была в конструкторе. Если это так, то в validateData у вас будет просто этот блок try-catch.

3. Но если вы создадите объект LibraryBook только для проверки данных (и не будете использовать этот конкретный экземпляр где-либо еще), то это означает, что что-то не так с тем, как разработан код.

4. Ну, есть два разных подхода к проверке. Проверка выполняется либо внутри конструктора, либо перед его вызовом. На мой взгляд, проверка в конструкторе — неплохая вещь, потому что она вообще не позволяет нам создавать недопустимые объекты. Единственным недостатком является то, что это приводит к небольшим накладным расходам из-за создания экземпляров объектов. Для несложных объектов, таких как LibraryBook, это не проблема, а лишь дает нам простой способ проверки данных и избежания дублирования кода.

Ответ №3:

Вы вызываете int.TryParse . Этот метод возвращает false, если он не может проанализировать значение — он никогда не выдаст исключение. Если вы хотите иметь исключение, вы должны принять int.Parse() . Но этот метод никогда не выдаст ваше пользовательское исключение CopyrightYearOutOfRange !

Ответ №4:

Потому что вы не создаете здесь экземпляр LibraryBook:

         try
        {
            int.TryParse(textBoxCopyrightYear.Text, out year);
        }
        catch (CopyrightYearOutOfRange ex)
        {
            MessageBox.Show(
                string.Format("{0}", ex.Message)
                , "Copyright out of range exception"
                , MessageBoxButtons.OK
                , MessageBoxIcon.Exclamation
                );
        }
  

Вы просто проверяете, является ли текст в textBoxCopyrightYear целочисленным значением

Комментарии:

1. Итак, как бы мне передать int и проверить его там?

Ответ №5:

 try
{
    // Is this where I'm making a mistake?
    int.TryParse(textBoxCopyrightYear.Text, out year);
}
  

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

В вашем случае вам не нужно использовать такую проверку в конструкторе, потому что вы можете просто добавить if предложение после int.TryParse .

 if(int.TryParse(textBoxCopyrightYear.Text, out year))
if(!isValidYear(year))
    MessageBox.Show(
        string.Format("{0}", ex.Message)
        , "Copyright out of range exception"
        , MessageBoxButtons.OK
        , MessageBoxIcon.Exclamation
        );