С#: Когда следует использовать 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. Это не исключительный случай, потому что, как говорили другие, вы должны планировать его.