66

I know.. I know... Performance is not the main concern here, but just for curiosity, what is better?

bool parsed = int.TryParse(string, out num);
if (parsed)
...

OR

try {
    int.Parse(string);
}
catch () {
    do something...
}
Randy Levy
  • 22,566
  • 4
  • 68
  • 94
renanleandrof
  • 6,699
  • 9
  • 45
  • 67

9 Answers9

97

Better is highly subjective. For instance, I personally prefer int.TryParse, since I most often don't care why the parsing fails, if it fails. However, int.Parse can (according to the documentation) throw three different exceptions:

  • the input is null
  • the input is not in a valid format
  • the input contains a number that produces an overflow

If you care about why it fails, then int.Parse is clearly the better choice.

As always, context is king.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • 2
    While I agree with the general thrust that context is king, I'd say that TryParse is *almost always* better, it's a bit more than a highly subjective personal preference. Your counterexample (distinguishing the different exceptions that can be thrown) is fairly unusual, and would probably be better coded with a catch block for each exception type rather than the catch all. – Joe Feb 09 '11 at 17:51
  • 2
    @Joe: yes, if you want to distinguish between the different exception types, anything else than specific catch blocks would seem very odd. My answer aimed on discussing `Parse` vs `TryParse` rather than the specific code samples in the question. As I have mentioned elsewhere in comments, I agree that `TryParse` is *almost always* the better way to go, but the keyword is "almost", not "always". – Fredrik Mörk Feb 09 '11 at 18:57
  • @Joe: I already made that argument. See the comment exchange to the original question. Fredrik's right about absolute statements never being true. (OMG a paradox!) – Cody Gray - on strike Feb 10 '11 at 04:17
  • Hail to the King, baby. – MrBoJangles Feb 28 '13 at 17:30
43

Is it exceptional for the conversion to sometimes fail, or is it expected and normal that the conversion will sometimes fail? If the former, use an exception. If the latter, avoid exceptions. Exceptions are called "exceptions" for a reason; you should only use them to handle exceptional circumstances.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    I like this explanation because I parse a lot of user data, and whether failure is expected or not (and what to do when it happens) shapes the entire project. – JYelton Feb 09 '11 at 15:31
  • Eric, I'd be interested to hear your thoughts on http://www.boost.org/community/error_handling.html: "``is this an exceptional (or unexpected) situation?'' This guideline has an attractive ring to it, but is usually a mistake... A more appropriate question to ask is: ``do we want stack unwinding here?''" – Jon Feb 15 '13 at 12:49
  • @Jon: Several things come to mind. First, that you can't argue with the tautology that exceptions are correct in those situations where you want the behaviour of an exception, but you can't learn anything from it either. Second, that "exceptional" and "unexpected" are two different things. And third, who says that stack unwinding has anything to do with it? That's an implementation detail of C#. Exceptions thrown in async methods don't unwind the stack; the stack is long gone. They signal a task that an exceptional event occurred. Don't confuse the semantics with the implementation. – Eric Lippert Feb 15 '13 at 15:47
  • I'd agree that the boost guideline raises the question, "when should we want stack unwinding?", but this quote also rings true: "The problem is that one person's 'exceptional' is another's 'expected'" Is a parse failure exceptional? Is hitting the end of a file exceptional? How do we objectively determine this? – Jon Feb 18 '13 at 00:22
25

If it is indeed expected that the conversion will sometimes fail, I like to use int.TryParse and such neatly on one line with the conditional (Ternary) operator, like this:

int myInt = int.TryParse(myString, out myInt) ? myInt : 0;

In this case zero will be used as a default value if the TryParse method fails.

Also really useful for nullable types, which will overwrite any default value with null if the conversion fails.

greg84
  • 7,541
  • 3
  • 36
  • 45
  • 1
    This is exactly equivalent to: `int myInt; int.TryParse(myString, out myInt);`. TryParse() already sets the result to 0 on failure. –  Jul 17 '13 at 19:55
  • 3
    Correct, but with my version you can specify an *alternative* default value, such as `10`. – greg84 Jul 18 '13 at 15:52
11

The first. The second is considered coding by exception.

George Johnston
  • 31,652
  • 27
  • 127
  • 172
8

Personally, I'd prefer:

if (int.TryParse(string, out num))
{
   ...
} 
Paddy
  • 33,309
  • 15
  • 79
  • 114
4

The first! You should not code by exception.

you could shorten it to

if (int.TryParse(string, out num))

Mr Shoubs
  • 14,629
  • 17
  • 68
  • 107
4

First, by far. As George said, second is coding by exception and has major performance impacts. And performance should be a concern, always.

Madeleine
  • 2,152
  • 2
  • 24
  • 35
2

Catching an Exception has more overhead, so I'll go for TryParse.

Plus, TryParse method does not throw an exception if the conversion fails. It eliminates the need to use exception handling to test for a FormatException in the event that s is invalid and cannot be successfully parsed.

That last part copy-pasted from here

tzup
  • 3,566
  • 3
  • 26
  • 34
2

Something else to keep in mind is that exceptions are logged (optionally) in the Visual Studio debug/output window. Even when the performance overhead of exceptions might be insignificant, writing a line of text for each exception when debugging can slow things right down. More noteworthy exceptions might be drowned amongst all the noise of failed integer parsing operations, too.

Quppa
  • 1,841
  • 20
  • 18