#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
);