Author avatar

Dániel Szabó

Arithmetic Operators and Their Contexts in C#

Dániel Szabó

  • Feb 28, 2020
  • 4 Min read
  • 432 Views
  • Feb 28, 2020
  • 4 Min read
  • 432 Views
Languages Frameworks and Tools
C#

Introduction

C# differentiates between two types of arithmetic operators. One is called unary, and the other is called binary. A unary operator takes a single operand, while a binary operator takes two operands.

In this guide, we will look at two contexts in which these arithmetic operators can be used. They are important as they affect the very core of your application and how exceptions are handled internally when using these operators on different datatypes. First, we will learn more about unary and binary operators, and then we'll look at their checked and unchecked contexts and how they modify the flow of an application.

Unary operators

  1. ++ (increment)
  2. -- (decrement)
  3. + (plus)
  4. - (minus)

Binary operators

  1. * (multiplication)
  2. / (division)
  3. % (remainder)
  4. + (addition)
  5. - (subtraction)

Arithmetic operators

These operators are strictly restricted. The type of data they are operating on binds their capabilities. For example, addition on two strings produces a different output than addition on two integers of floating-point values. The above-mentioned operators are supported by all integral and floating-point numeric types. The integral numeric type is nothing but a fancy word for integers.

Arithmetic Overflow

Arithmetic overflow occurs when the result of an expression cannot fit into the maximum size allowed by a specific datatype.

Let's demonstrate this with a small sample code. We will try to add 1 to the MaxValue of the int datatype.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System;

namespace Pluralsight
{
    public class ArithOverflow
    {
        
        public static void Main()
        {
            int maximum = int.MaxValue;
            Console.WriteLine(maximum + 1);
        }
    }
}
csharp

The output is as follows.

1
-2147483648
bash

As we can see, the output is wrong, and no exception is thrown. The consequence of this is hard to measure. If this value is passed further to other applications that expect a predefined set of values, they could crash or modify the whole flow of the app. Let's see how checked{} context can help.

Checked Context

We can use checked{} to make sure an exception is thrown in cases of arithmetic overflow. We'll need to modfiy the code as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using System;

namespace Pluralsight
{
    public class ArithOverflow
    {
        
        public static void Main()
        {
            checked {
            int maximum = int.MaxValue;
            Console.WriteLine(maximum + 1);
            }
        }
    }
}
csharp

Upon execution we recieve the following error.

1
System.OverflowException: 'Arithmetic operation resulted in an overflow.'
bash

It is very important to mention that this is a runtime error. The CLR has no way of predicting these before compilation. All that is left to do is to handle the exception at runtime from the application's perspective.

Unchecked Context

You may be wondering, as I did the first time I met with this concept, "Why is it not the default for C# to use checked context?"

Well, the answer is not simple. As per language specification, The default behavior is unchecked unless specified otherwise by external factors, like compiler switches and the configuration of the execution environment. Using checked context has a serious performance impact. Let's not make an elephant out of the mouse, as throughout the development of C# Microsoft checked how people stretched the language. It was found that in most cases, this default behavior is perfectly fine. Arithmetic overflows are more of a corner case than a regular occurence. Of course, when they happen and goes unnoticed, it hurts.

Conclusion

In this guide, we had a little introduction to arithmetic operators. We also learned the difference between checked and unchecked contexts and their impact on execution. The most important thing we learned is the default approach C# uses in this context. I hope this guide has been informative for you and I would like to thank you for reading it!

6