views:

1154

answers:

4

We all know the effects that lots of thrown exceptions can have over the performance of our applications, thus, we should stay away from things like using exceptions for control flow. After this statement I must confess that when coding I didn't care that much about this. I've been working mostly on Java platform but lately I was doing it on .NET platform and just found out this handy method: public static bool TryParse(string s,out int result) ,which allows you to transform a String into int whithout raise an exception. From that moment on, I'm keeping on using it. I just wanted to ask you about your preferences regarding the use of public static bool TryParse(string s,out int result) or public static int ToInt32(string value).

And from the point of view of Java, just pointing that it's missing such a similar method, despite we could get it through things like:

boolean isInteger = Pattern.matches("^\d*$", myString);

Thanks.

+7  A: 

Yes, Java is missing a similar method, although without out parameters it's actually pretty difficult to express (while wanting to return a primitive). Generally, though, in C# you should use TryParse if you expect the value to not be an integer sometimes, and ToInt32 otherwise; this way the "exceptional" situation is treated as such.

In particular if performance is your main reason for wanting TryParse, the regex matches method you post is considerably worse. The performance "expense" of Exceptions (which is, in reality, very minimal) is dwarfed by how much using them wrongly can fuzz easy understanding of control flow.

Calum
BTW, there would be alternative ways for getting that in Java. One would be the use of Integer instead of int and the other to put int within an array and pass it to the method.
Juan Carlos Blanco Martínez
Yeah, that's why I mentioned the "while wanting to return a primitive" part. It's possible but never neat, essentially.
Calum
+1  A: 

For that purpose in Java you can use the well know StringUtils (on the commons-lang), this class have a method isNumeric

Probably you can take a look to the code that those guys have write for that function:

public static boolean isNumeric(String str) {
  if (str == null) {
    return false;
  }
  int sz = str.length();
  for (int i = 0; i < sz; i++) {
    if (Character.isDigit(str.charAt(i)) == false) {
      return false;
    }
  }
  return true;
 }

I am not saying that this is the most efficient way to do it, but there is another alternative for you without using regex. Good luck!

David Santamaria
What's with this "== false" stuff? I can't believe I'm seeing that in Apache source code!
Alan Moore
The problem with "== false" is what happens if you accidentally use only one "=". The type of the expression is still boolean, so it compiles but you end up with a what could be a subtle, intermittent bug. It's just a good habit to get out of.
Alan Moore
if ( !Character.isDigit(str.charAt(i)) )
Adam Tolley
+1  A: 

I don't know about C#, but in Java exceptions are only expensive when they're actually thrown, but then they're very expensive indeed. If you expect a significant fraction of the strings to be invalid, it's worth your while to validate them first, even if you use a regex.

But don't use String.matches() or Pattern.matches() to apply the regex; those methods recompile the regex every time you call them. Instead, compile the regex ahead of time and save it as a Pattern object, then do your validating with that. In my tests, parsing a list of 10,000 strings of which 20% were invalid, pre-validating with a Pattern is almost twice as fast as using Integer.parseInt() alone and catching the exceptions.

However, this discussion only applies if you're doing a lot of conversions in a tight loop. If you're only doing them once in a while, like when you accept user input, letting Integer.parseInt() do the validating is fine. And if you do choose to validate with a regex, you'll need a much better regex than ^\d*$ - that regex will match the empty string as well as "numbers" larger than Integer.MAX_VALUE, and it won't match negative numbers at all.

Alan Moore
A: 

I just wanted to ask you about your preferences regarding the use of public static bool TryParse(string s,out int result) or public static int ToInt32(string value).

Yes, I use TryParse except where I expect the value to always be valid. I find that it reads cleaner than using the exceptions. Even if I want an exception, I usually want to customize the message or throw my own custom exception; hence, I use TryParse and manually throw an exception.

In both Java and C#, I try to catch the minimum set of exceptions possible. In Java, that means I have to separately catch NullPointerException and NumberFormatException in response to Number.ValueOf(...); alternatively, I can catch "Exception" and risk catching something unintended. With TryParse in C#, I don't worry about that at all.

James Schek