Validating an Integer

Have you ever wondered how to check if a number is an integer in C#?  Wondered why Convert.ToInt32() surrounded by a try catch is so slow?  Well, this article is for you then. As everyone should know, catching an exception is an extremely time consuming task, but there's no obvious way to check if a string is actually an integer.  And before the visual basic people all say about Microsoft.VisualBasic.Information.IsNumeric this is actually simply a try...catch around a Convert.ToInt32 call.

Okay, so what is the performance drop incurred by using a try...catch and why should you worry?

Well, it's slow - 1000 iterations of try...catch around a Convert.ToInt32() comes to 2515.625 ms.  Programmatically that's a HORRID use of CPU time. Some people (particularly on blogs.msdn.com's comments) have suggested that this is simply something you must incur, however due to NumberStyles (in System.Globalization) containing an entry for Integer it needn't be.

We can use Double.TryParse without the risk that the double we'll be getting back will contain anything but a valid integer. This is amazingly faster - 100,000 (100 times more than with a try...catch!) worst case scenarios come to a grand total of 46.875 ms of cpu time used up.  A much better overhead. It returns True if the string was an integer and false if not - altering the value of the double passed into it as an out parameter to be the correct amount if it succeeds.  Note that the if statements are just there to confuse the compiler so it doesn't optimise out the whole contents of each for loop.

Here's an example application (sorry, no walkthrough as I have too little time, but this should be simple enough!):

using System;
using System.Globalization;
namespace BlogExamples.IntegerValidation
{
  class IntegerValidator
  {
      static void Main(string[] args)
      {
      Console.WriteLine("Comparison of speed of try..catch checking of integers");
      Console.WriteLine("1000 iterations of try...catch Convert.ToInt32()");
      DateTime before = DateTime.Now;
      for (int i=0; i<1000; i++)
      {
        try
        {
            int t = Convert.ToInt32("testing");
            if (t>1000)
            {
              Console.WriteLine("Optimisation cheating");
            }
        }
        catch
        {
        }
      }
      TimeSpan duration = DateTime.Now - before;
      Console.WriteLine(duration.TotalMilliseconds+" ms total");
      CultureInfo MyCultureInfo = new CultureInfo("en-GB");
      Console.WriteLine("100000 iterations of Double.TryParse() (to be fair!)");
      DateTime before2 = DateTime.Now;
      for (int i=0; i<100000; i++)
      {
            double d = 0;
            Double.TryParse("testing", System.Globalization.NumberStyles.Integer, MyCultureInfo, out d);
            if (d>1000)
            {
            Console.WriteLine("Optimisation cheating");
            }
        }
        TimeSpan duration2 = DateTime.Now - before2;
        Console.WriteLine(duration2.TotalMilliseconds+" ms total");
        Console.ReadLine();
      }
  }
}

Which when run on my machine reports the following:

Comparison of speed of try..catch checking of integers
1000 iterations of try...catch Convert.ToInt32()
2515.625 ms total
100000 iterations of Double.TryParse() (to be fair!)
46.875 ms total

You might also like...

Comments

Simon Soanes

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Brevity is the soul of wit” - Shakespeare