С#: Когда следует использовать TryParse?
Я понимаю, что это не бросает исключение, и из-за этого оно может быть заметно быстрее, но также, скорее всего, вы используете его для преобразования ввода в данные, которые вы можете использовать, поэтому я не думаю, что он использовался так часто, чтобы сделать большую разницу в плане производительности.
Во всяком случае, примеры, которые я видел, находятся вдоль строк блока if/else с TryParse
, а другой - с сообщением об ошибке. И для меня это в основном то же самое, что использование блока try/catch с уловом, возвращающим сообщение об ошибке.
Итак, я что-то упускаю? Есть ли ситуация, когда это действительно полезно?
Ответы
Ответ 1
Это довольно просто: используйте Parse
, если вы хотите исключение, когда вы сталкиваетесь с недействительными данными; используйте TryParse
, если вы этого не сделаете. Поэтому ваш вопрос выглядит следующим образом:
Почему вы не хотите исключение, если данные недействительны?
Исключения должны использоваться только в исключительных случаях, а недопустимые данные могут быть не исключительным случаем. Возможно, вы пишете программу очистки данных, которая ожидает получить недействительные данные, и попытается сделать вывод о том, что разумное значение имеет, когда данные недействительны. Возможно, данные не так важны, и вы можете просто пропустить запись, содержащую ее.
Это зависит от контекста, и выбор методов Parse
и TryParse
позволяет вам выбрать соответствующий механизм синтаксического анализа для вашего.
Ответ 2
Помимо аспекта производительности, о котором вы упоминали, есть и семантическая разница:
Использование try/catch предназначено для исключительных обстоятельств. Ввод неверных данных - это то, что вы ожидаете, а не что-то исключительное.
Ответ 3
По возможности используйте TryParse
- использование его намного дешевле, чем получение брошенного исключения.
Ответ 4
Предположим, что вы читаете файл журнала:
public IEnumerable<LogEntry> GetAllValidEntries() {
while (!logReader.Finished) {
string nextLine = logReader.ReadLine();
LogEntry nextEntry;
if (TryParseLogEntry(nextLine, out nextEntry))
yield return nextEntry;
}
}
private bool TryParseLogEntry(string line, out LogEntry logEntry) {
logEntry = null;
if (string.IsNullOrEmpty(line))
return false;
string[] cells = line.Split(';');
if (cells.Length < 3)
return false;
DateTime time;
decimal price;
int quantity;
// We just want to read this line of text as a LogEntry
// IF it is valid; otherwise, there no reason to throw
// an error in the user face
if (!DateTime.TryParse(cells[0], out time) ||
!decimal.TryParse(cells[1], out price) ||
!int.TryParse(cells[2], out quantity))
return false;
logEntry = new LogEntry(time, price, quantity);
return true;
}
Поскольку вся цель вышеуказанного кода заключается в извлечении действительных элементов из последовательности (предположительно ожидается, что она содержит некоторые недопустимые элементы), я думаю, что методы TryParse
делают много больше смысла в этот случай, чем методы Parse
, которые требуют действительного ввода.
Ответ 5
Если вам нужно установить значение по умолчанию при неудачном разборе, TryParse вместе с if - отличный способ сделать это.
Ответ 6
Well int.TryParse возвращает bool, позволяя вам проверить, было ли это успешным, а не ловить исключение. Я обычно использую его в ситуациях, когда если информация была успешно переведена, я хочу ее использовать, но если это не так, это не важно, я могу игнорировать отказ в таком состоянии, поскольку я хочу использовать значение по умолчанию, если я не получу значимого значение, в этом случае я переопределю его, но если значение не имеет смысла, я сохраню значение по умолчанию.
Теория утверждает, что исключения изначально дороги, и поэтому вы не должны использовать их для диктовки потока программы. Вы должны поймать их там, где что-то семантически неправильно, а не что-то, что может интерпретироваться как поток данных.
Ответ 7
В случаях, которые либо не возражают против установки значения 0 при неудавшемся анализе (возможно, недопустимый ввод), либо в случаях, когда требуется краткость, код возврата TryParse позволяет это.
Ответ 8
Каждый раз, когда у вас есть синтаксический анализ для выполнения, поскольку он является менее дешевым в использовании, чем исключение, плюс вы можете сделать его частью простой инструкции if вместо большого блока try... catch.
Ответ 9
Я не обезьяна С#, но...
Прерывание прерывает нормальный поток кода, передавая обработку блоку catch.
TryParse даст вам больше контроля (например, выделите ошибку в текстовом поле), а затем опирается на механизм исключения.
Ответ 10
Если вы выполняете проверку ввода в форме, вы можете установить ErrorProvider на элемент управления (или MessageBox или какое-либо другое уведомление), когда он вернет false. Это не исключительный случай, потому что, как говорили другие, вы должны планировать его.