53

Handling integer overflow is a common task, but what's the best way to handle it in C#? Is there some syntactic sugar to make it simpler than with other languages? Or is this really the best way?

int x = foo();
int test = x * common;
if(test / common != x)
    Console.WriteLine("oh noes!");
else
    Console.WriteLine("safe!");
dreadwail
  • 15,098
  • 21
  • 65
  • 96

6 Answers6

119

I haven't needed to use this often, but you can use the checked keyword:

int x = foo();
int test = checked(x * common);

Will result in a runtime exception if overflows. From MSDN:

In a checked context, if an expression produces a value that is outside the range of the destination type, the result depends on whether the expression is constant or non-constant. Constant expressions cause compile time errors, while non-constant expressions are evaluated at run time and raise exceptions.

I should also point out that there is another C# keyword, unchecked, which of course does the opposite of checked and ignores overflows. You might wonder when you'd ever use unchecked since it appears to be the default behavior. Well, there is a C# compiler option that defines how expressions outside of checked and unchecked are handled: /checked. You can set it under the advanced build settings of your project.

If you have a lot of expressions that need to be checked, the simplest thing to do would actually be to set the /checked build option. Then any expression that overflows, unless wrapped in unchecked, would result in a runtime exception.

Wollmich
  • 1,616
  • 1
  • 18
  • 46
Michael Petito
  • 12,891
  • 4
  • 40
  • 54
  • 3
    Why is the default behavior is unchecked? Is there any performance concerns on using checked? – KFL Nov 05 '13 at 01:44
  • 3
    @KFL "Because checking for overflow takes time, the use of unchecked code in situations where there is no danger of overflow might improve performance. However, if overflow is a possibility, a checked environment should be used." See http://msdn.microsoft.com/en-us/library/a569z7k8.aspx. I also believe that the default is unchecked because it parallels the C / C++ behavior. – Michael Petito Nov 05 '13 at 01:55
  • 1
    There are cases where overflow is useful, for instance the TCP sequence number. An unsigned int just wraps around to zero, so all that's needed is the increment operator. –  Sep 25 '14 at 18:03
  • Does unchecked produce same results in case of overflow on all machines?? –  Dec 10 '15 at 12:00
  • Updated url reference for 'checked' - https://msdn.microsoft.com/en-us/library/74b4xzyw(v=vs.140).aspx – Saurabh Kumar Jul 23 '16 at 04:06
  • This is useful for unexpected overflow. Be aware of the added overhead of the exception if overflows are common. – hultqvist Apr 14 '17 at 18:04
22

Try the following

int x = foo();
try {
  int test = checked (x * common);
  Console.WriteLine("safe!");
} catch (OverflowException) {
  Console.WriteLine("oh noes!");
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
7

The best way is as Micheal Said - use Checked keyword. This can be done as :

int x = int.MaxValue;
try   
{
    checked
    {
        int test = x * 2;
        Console.WriteLine("No Overflow!");
    }
}
catch (OverflowException ex)
{
   Console.WriteLine("Overflow Exception caught as: " + ex.ToString());
}
Henrik
  • 613
  • 4
  • 11
Chinjoo
  • 2,697
  • 6
  • 28
  • 45
  • You need to format your code (insert 4 spaces prior to it and the site will automatically pick up the formatting and syntax highlighting. – dreadwail Jun 02 '10 at 19:30
6

Sometimes, the simplest way is the best way. I can't think a better way to write what you wrote, but you can short it to:

int x = foo();

if ((x * common) / common != x)
    Console.WriteLine("oh noes!");
else
    Console.WriteLine("safe!");

Note that I didn't remove the x variable because it'd be foolish to call the foo() three times.

Alon Gubkin
  • 56,458
  • 54
  • 195
  • 288
  • 1
    Now I wonder if the compiler would ever optimize that expression away entirely? – Michael Petito Jun 02 '10 at 04:49
  • 3
    USefull, unless of course you are planning on using the result (x*common), in that case your shortening would require the calculation to be done twice ... – Cobusve Jun 02 '10 at 08:56
4

Old thread, but I just ran into this. I didn't want to use exceptions. What I ended up with was:

long a = (long)b * (long)c;
if(a>int.MaxValue || a<int.MinValue)
    do whatever you want with the overflow
return((int)a);
YourUncleBob
  • 85
  • 1
  • 1
  • 1
    This won't work. `int.MaxValue + 1` gives you -2147483648 or `int.MinValue`. so `a` can never be larger than MaxValue or smaller than MinValue. Think of numbers as a line like this: `-2147483648, -2147483647, ... 0 ... 2147483646, 2147483647` when you go over the max value, it flows back to the smallest. – Ray Cheng Apr 08 '15 at 23:23
  • 7
    you missed the fact that he/she converted to long before checking against the bounds of the int. so it would work as long it doesnt overflow the long. – hammett Jan 06 '16 at 04:52
0

So, I ran into this far after the fact, and it mostly answered my question, but for my particular case (in the event anyone else has the same requirements), I wanted anything that would overflow the positive value of a signed int to just settle at int.MaxValue:

int x = int.MaxValue - 3;
int someval = foo();

try
{
   x += someval;
}

catch (OverflowException)
{
   x = int.MaxValue;
}
Jesse Williams
  • 653
  • 7
  • 21
  • 1
    The exception wouldn't get thrown unless you compile with ```/checked```, or use the ```checked``` keyword, correct? – Paul Knopf Dec 13 '16 at 13:38