Introduction
This article addresses an issue with the implementation of Integer values in .NET that one should be aware of when performing calculations on integer values that may overrun the maximum or minimum values of the integer type. Oddly enough, or at least it seems odd to me, when the integer value mechanization details were ironed out it was apparently decided that the best way to normally handle overrunning the maximum or minimum values of an integer would be to simply wrap to the opposite end of available values without throwing an error. That can certainly lead to rather disastrous results in calculations that may creep up on either of the extreme ends of the possible range of values.
Normally one would mitigate this by selecting a different data type less likely to be overrun by exceeding either the minimum or maximum values acceptable for that integer type. However, .NET does offer the means to force throwing an error when the upper or lower limits of the data are going to be exceeded by any given calculation; it does take a little more work to safely implement such calculations but not much; it is certainly worth having the peace of mind that comes from knowing that wrapping the values will be eliminated in the event that an overrun is going to occur.
Attached Project
The attached project contains a single Windows Forms project that provides examples of unsafe and safe calculations involving addition and subtraction of numbers at the minimum and maximum limits of the integer type.
There are four examples used to illustrate the point:
- Adding one to the maximum integer value without using the 'checked' function.
- Adding one to the maximum integer value whilst using the 'checked' function.
- Subtracting one from the minimum integer value without using the 'checked' function.
- Subtracting one from the minimum integer value whilst using the 'checked' function.
To the point, if you add one to the maximum value without using the 'checked' function, the result will wrap to become the minimum possible integer values.
Similarly, if you subtract one from the minimum integer value without using the 'checked' function, the result will be the maximum possible integer value.
Once ran, the application is per the following figure:
Figure 1: Test Application
At the top of the form are the minimum and maximum values for an integer on my machine. The two groups below either add one to the maximum value or subtract one from the minimum value. The top option does not use the 'checked' function and it does not throw an error. If you click the button you will see the result or adding one, for example, to the maximum value is in fact now the minimum value. Maybe not exactly what you had in mind for the result.
The bottom option of each test performs the same calculaton but they both rely on the 'checked' function to prevent the overflow. In those cases, the attempt will result in an exception which is in turn caught in a try-catch block and used to display an error message to the user.
The code for the project is annotated and you can follow along with it by reading the comments and examining the code. At the end of it, the value of using the 'checked' function should be relatively obvious.
Main Form Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AddsUp
{
public partial class Form1 : Form
{
// set up two integer values to
// contain the minimum and maximum
// integer values
int MaxValue;
int MinValue;
public Form1()
{
InitializeComponent();
// set the variables to min and max value
MaxValue = int.MaxValue;
MinValue = int.MinValue;
// display the minimum and maximum values
lblMaxValue.Text =
lblMaxValue.Text + ": " + MaxValue.ToString();
lblMinValue.Text =
lblMinValue.Text + ": " + MinValue.ToString();
// preload the textboxes used in the calculations
txtMaxValue.Text =
MaxValue.ToString();
txtCheckedMaxValue.Text = MaxValue.ToString();
txtMinValue.Text =
MinValue.ToString();
txtCheckedMinValue.Text = MinValue.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
}
/// <summary>
/// Unchecked, overrunning the maximum integer value
will force the
/// number to wrap; that is, adding one to the maximum
integer value
/// will not throw an error and it will wrap the value
to the minimum
/// integer value.
Change the number subtracted from 1 to 10 or any
/// larger value and note the effect; certainly not
anything you'd want
/// to see in anything important and involving
calculations.
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
private void btnMaxPlus1_Click(object sender, EventArgs e)
{
try
{
if (!String.IsNullOrEmpty(txtMaxValue.Text))
txtMaxPlus1Result.Text =Convert.ToString(Convert.ToInt32(txtMaxValue.Text) + 1);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Error");

Scott LyslePosted Nov 15, 2012, 12:24 PM
Thanks Sam, the mechanization detail I had in mind was how they managed the overflow event - I would have preferred it if throwing the expection was the default behavior but it is not. The wrap is the default and you have to use the checked function to enforce capture of the error. I can't imagine any situation where the default behaviour would have been acceptable in any sort of application involving calculations of integer values. It is as you said, "It is typical for computers to produce and overflow exception" but again, that is the not default behaviour in this case. Anyway, I thought it was interesting point to make and I appreciate you taking the time to give it a read.
Sam HobbsPosted Nov 15, 2012, 11:44 AM
You say "when the integer value mechanization details were ironed out". That was done more than half a century ago. Computer arithmetic might be a form of Modular arithmetic, first described about 1750. In computers, I think what you call overrun is typically called overflow. It is typical for computers to produce an overflow exception, although I am not sure of the terminology. Computers also typically have a carry and/or overflow flag. The carry flag is a normal way to support numbers greater than what the computer hardware supports. See: http://en.wikipedia.org/wiki/Arithmetic_overflow