What is the C# "checked" keyword for?
Categories:
Understanding the C# 'checked' Keyword for Overflow Control

Explore the C# 'checked' keyword, its role in detecting arithmetic overflows, and how it enhances application robustness by preventing silent data corruption.
In C#, arithmetic operations on integral types (like int
, long
, short
, byte
) can sometimes result in an overflow or underflow. This occurs when the result of an operation exceeds the maximum or falls below the minimum value that the data type can represent. By default, C# handles these situations by wrapping the result, meaning the value 'rolls over' to the opposite end of the type's range without throwing an exception. While this behavior can be desirable in some low-level programming contexts, it often leads to subtle and hard-to-debug errors in business logic or application code. The checked
keyword provides a mechanism to explicitly enable overflow checking, transforming these silent wraps into exceptions, thereby making potential issues immediately apparent.
What is Arithmetic Overflow?
Arithmetic overflow happens when an operation produces a result that is too large for the data type storing it. For example, if you add 1 to the maximum value of an int
(which is 2,147,483,647
), the result will wrap around to the minimum int
value (-2,147,483,648
) if not checked. This 'silent' wrapping can lead to incorrect calculations and unexpected program behavior. The checked
keyword forces the Common Language Runtime (CLR) to monitor these operations and throw an OverflowException
if an overflow occurs.
int maxValue = int.MaxValue; // 2,147,483,647
int resultUnchecked = maxValue + 1; // resultUnchecked becomes -2,147,483,648 (wraps around)
Console.WriteLine($"Unchecked result: {resultUnchecked}");
try
{
checked
{
int resultChecked = maxValue + 1; // This will throw an OverflowException
Console.WriteLine($"Checked result: {resultChecked}");
}
}
catch (OverflowException ex)
{
Console.WriteLine($"Checked operation caught an error: {ex.Message}");
}
Demonstrating unchecked vs. checked arithmetic overflow
Using the 'checked' Keyword
The checked
keyword can be used in two main ways: as an operator for a single expression or as a statement block for multiple expressions. When applied to an expression, it ensures that only that specific operation is checked for overflow. When used as a block, all integral arithmetic operations within that block are subject to overflow checking. This allows for fine-grained control over where overflow detection is enabled, balancing performance considerations with the need for robustness.
// Using 'checked' as an operator
int a = 2000000000;
int b = 2000000000;
try
{
int sum = checked(a + b); // Only this addition is checked
Console.WriteLine($"Checked sum (operator): {sum}");
}
catch (OverflowException ex)
{
Console.WriteLine($"Overflow caught (operator): {ex.Message}");
}
// Using 'checked' as a statement block
int x = int.MaxValue;
int y = int.MaxValue;
try
{
checked
{
int product = x * y; // This multiplication is checked
Console.WriteLine($"Checked product (block): {product}");
}
}
catch (OverflowException ex)
{
Console.WriteLine($"Overflow caught (block): {ex.Message}");
}
Examples of 'checked' as an operator and a statement block
flowchart TD A[Start Program] --> B{Arithmetic Operation?} B -- Yes --> C{Is 'checked' context active?} C -- Yes --> D{Result overflows data type?} D -- Yes --> E[Throw OverflowException] D -- No --> F[Store Result] C -- No --> F B -- No --> G[Continue Program] E --> G F --> G
Flowchart illustrating C# arithmetic overflow checking logic
Compiler Options and 'unchecked'
By default, C# projects compile in an unchecked
context, meaning overflows are ignored. However, you can change this behavior at the project level by setting the /checked
compiler option (or checking the 'Check for arithmetic overflow/underflow' box in project properties in Visual Studio). If you compile with /checked
, all arithmetic operations in your code will be checked by default. In such a scenario, you might need the unchecked
keyword to explicitly disable overflow checking for specific operations where wrapping behavior is intended or performance is critical.
// Assuming project is compiled with /checked option
int largeValue = int.MaxValue;
try
{
int result = largeValue + 1; // This would throw OverflowException by default
}
catch (OverflowException ex)
{
Console.WriteLine($"Default checked context caught: {ex.Message}");
}
// Using 'unchecked' to explicitly allow wrapping
unchecked
{
int wrappedResult = largeValue + 1; // This will wrap around to int.MinValue
Console.WriteLine($"Explicitly unchecked result: {wrappedResult}");
}
Using 'unchecked' in a project compiled with default overflow checking
checked
adds a small performance overhead due to the extra checks, for most application code, the benefit of catching potential data corruption far outweighs this cost. Use checked
where numerical integrity is paramount, especially with user input or financial calculations.