.NET C# Integer Types – And a Tricky Puzzle to Master Them
Introduction
In .NET C#, numbers aren’t just numbers. Choosing the correct integer type is essential for writing safe, efficient, and bug-free code. Whether you’re working on finance calculations, embedded systems, or everyday logic, understanding how different integer types work — and how they interact — is crucial.
This article covers:
- The different integer types in C#
- Their ranges and signed/unsigned nature
- Common pitfalls (like overflows)
- A fun puzzle to test your skills
Integer Types in C#
C# provides both signed and unsigned integer types, with varying sizes. Here’s a summary:
Type | Size | Signed | Range |
---|---|---|---|
byte |
8-bit | ![]() |
0 to 255 |
sbyte |
8-bit | ![]() |
-128 to 127 |
short |
16-bit | ![]() |
-32,768 to 32,767 |
ushort |
16-bit | ![]() |
0 to 65,535 |
int |
32-bit | ![]() |
-2,147,483,648 to 2,147,483,647 |
uint |
32-bit | ![]() |
0 to 4,294,967,295 |
long |
64-bit | ![]() |
−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
ulong |
64-bit | ![]() |
0 to 18,446,744,073,709,551,615 |
Common Pitfalls to Watch For
1. Overflow & Underflow
byte b = 255;
b++; // Becomes 0 due to overflow (wraps around)
2. Implicit vs. Explicit Casting
int a = 1000;
byte b = (byte)a; // b = 1000 % 256 = 232 (data loss)
3. Signed vs. Unsigned Comparisons
int x = -1;
uint y = 1;
Console.WriteLine(x < y); // True
Console.WriteLine((uint)x < y); // False! (because (uint)-1 is 4294967295)
The Tricky Puzzle
Let’s test your integer knowledge!
Puzzle: What will this print?
using System;
class Program
{
static void Main()
{
byte a = 250;
sbyte b = -10;
int c = a + b;
Console.WriteLine($"a + b = {c}");
byte d = (byte)(a + b);
Console.WriteLine($"(byte)(a + b) = {d}");
unchecked
{
byte e = (byte)(a + 10);
Console.WriteLine($"unchecked byte: {e}");
}
checked
{
try
{
byte f = checked((byte)(a + 10));
Console.WriteLine($"checked byte: {f}");
}
catch (OverflowException)
{
Console.WriteLine("Overflow detected!");
}
}
}
}
Puzzle Explanation
Let’s break it down:
Line 1:
byte a = 250;
sbyte b = -10;
a
is 250 (byte),b
is -10 (sbyte)
Line 2:
int c = a + b;
- Implicitly promoted to
int
, so:250 + (-10) = 240
Output: a + b = 240
Line 3:
byte d = (byte)(a + b); // (byte)240 => 240 (within range)
Output: (byte)(a + b) = 240
Line 4 (unchecked context):
byte e = (byte)(a + 10); // 250 + 10 = 260 => wraps to 260 % 256 = 4
Output: unchecked byte: 4
Line 5 (checked context):
byte f = checked((byte)(a + 10)); // OverflowException at runtime
Output: Overflow detected!
Key Takeaways
- Integer types differ in size, range, and signed-ness — understand these before choosing a type.
- Use
checked
andunchecked
to control overflow behavior. - Be cautious when mixing types (e.g.,
byte
+sbyte
, orint
withuint
). - Use explicit casting carefully to avoid unexpected data loss.
Try It Yourself
Modify the values in the puzzle above and see how behavior changes:
- What if
a = 255
andb = 1
? - What if you remove
checked
? - Try assigning
int
values toushort
orsbyte
directly.
Conclusion
Integer types may seem simple, but their nuances can lead to unexpected behavior — especially in high-performance or low-level logic. Mastering them early helps you write safer, more robust .NET applications.