The checked
and unchecked
keywords define how operations handle mathematical overflow. "Overflow" in the context of the checked
and unchecked
keywords is when an integer arithmetic operation results in a value which is greater in magnitude than the target data type can represent.
When overflow occurs within a checked
block (or when the compiler is set to globally use checked arithmetic), an exception is thrown to warn of undesired behavior. Meanwhile, in an unchecked
block, overflow is silent: no exceptions are thrown, and the value will simply wrap around to the opposite boundary. This can lead to subtle, hard to find bugs.
Since most arithmetic operations are done on values that are not large or small enough to overflow, most of the time, there is no need to explicitly define a block as checked
. Care needs to be taken when doing arithmetic on unbounded input that may cause overflow, for example when doing arithmetic in recursive functions or while taking user input.
Neither checked
nor unchecked
affect floating point arithmetic operations.
When a block or expression is declared as unchecked
, any arithmetic operations inside it are allowed to overflow without causing an error. An example where this behavior is desired would be the calculation of a checksum, where the value is allowed to "wrap around" during calculation:
byte Checksum(byte[] data) {
byte result = 0;
for (int i = 0; i < data.Length; i++) {
result = unchecked(result + data[i]); // unchecked expression
}
return result;
}
One of the most common uses for unchecked
is implementing a custom override for object.GetHashCode()
, a type of checksum. You can see the keyword's use in the answers to this question: What is the best algorithm for an overridden System.Object.GetHashCode?.
When a block or expression is declared as checked
, any arithmetic operation that causes an overflow results in an OverflowException
being thrown.
int SafeSum(int x, int y) {
checked { // checked block
return x + y;
}
}
Both checked and unchecked may be in block and expression form.
Checked and unchecked blocks do not affect called methods, only operators called directly in the current method. For example, Enum.ToObject()
, Convert.ToInt32()
, and user-defined operators are not affected by custom checked/unchecked contexts.
Note: The default overflow default behavior (checked vs. unchecked) may be changed in the Project Properties or through the /checked[+|-] command line switch. It is common to default to checked operations for debug builds and unchecked for release builds. The checked
and unchecked
keywords would then be used only where a default approach does not apply and you need an explicit behavior to ensure correctness.