Int and UInt in C#
By That Developer Guy
(Learn, Build, and Unlock Your Inner Dev)
What Are Int and UInt?
The int
and uint
types are the most commonly used integer types in C#. They store 32-bit (4-byte) whole numbers, providing a good balance between range and memory usage. This makes them the default choice for most integer values in C# programming.
The key difference between them:
- int - Signed (can hold positive and negative numbers)
- uint - Unsigned (positive numbers only)
Data Type | Range | Memory | Struct |
---|---|---|---|
int | -2,147,483,648 to 2,147,483,647 | 4 bytes (32 bits) | System.Int32 |
uint | 0 to 4,294,967,295 | 4 bytes (32 bits) | System.UInt32 |
Important: int
is by far the most commonly used integer type in C#. When you write a number literal like 42
, the compiler treats it as an int
by default.
When to Use Int and UInt
Int (Most Common)
- Default choice for counting, indexing, and general integer values
- Loop counters and array indices
- User ages, scores, quantities
- Calculations involving positive and negative numbers
- Database IDs and primary keys
- Year values, days, hours, minutes
- Any integer value where you might need negatives
UInt (Less Common)
- When you're certain values will never be negative
- Working with binary data or bitwise operations
- Interoperating with APIs that require unsigned integers
- When you need the extra positive range (up to 4.2 billion)
- File sizes and memory addresses
- Color values and pixel data
Best Practice: Use int
unless you have a specific reason to use uint
. Most C# APIs and methods expect int
, and using uint
can sometimes require extra casting.
Basic Syntax
Declaration and Initialization
// Using int keyword (recommended)
int count = 10;
int temperature = -5;
int maxStudents = 100;
// Using System.Int32 struct
System.Int32 number = 42;
// Unsigned integer
uint population = 7900000000;
uint distance = 384400; // kilometers to moon
// Using System.UInt32 struct
System.UInt32 largeValue = 3000000000;
Using 'int' vs 'Int32'
The lowercase int
is an alias for System.Int32
. They are identical, but int
is the standard, preferred way to declare integer variables.
using System;
namespace GetCoding
{
class Program
{
static void Main(string[] args)
{
int a = 0; // Recommended - simple and clean
Int32 b = 0; // Works in .NET 8+, needs 'using System;' in earlier versions
uint c = 0; // Recommended
UInt32 d = 0; // Works in .NET 8+, needs 'using System;' in earlier versions
}
}
}
Best Practice: Always use lowercase int
and uint
for consistency with C# conventions.
Using var with Int and UInt
When using the var
keyword, numeric literals default to int
, so be careful when working with uint
.
int a = 0; // Explicitly int
var b = 0; // Defaults to int - no casting needed
var c = (int)0; // Explicitly int (casting unnecessary here)
uint d = 0; // Explicitly uint
var e = (uint)0; // Must cast to make it uint
var f = new uint(); // This is uint with default value of 0
// Examples
var score = 100; // This is int
var population = 3000000000; // This is int, but causes error! Value too large
var population = 3000000000u; // Use 'u' suffix for uint literal
Pro Tip: Add a u
or U
suffix to numeric literals to make them uint
:
uint bigNumber = 3000000000u; // u suffix makes it uint
var alsoBig = 3000000000U; // U suffix also works
Properties: MinValue and MaxValue
Every integer type in C# has MinValue
and MaxValue
properties that define the boundaries of values the type can hold.
using System;
class Program
{
static void Main(string[] args)
{
// Int properties
int intMin = int.MinValue; // -2,147,483,648
int intMax = int.MaxValue; // 2,147,483,647
// UInt properties
uint uintMin = uint.MinValue; // 0
uint uintMax = uint.MaxValue; // 4,294,967,295
// Display the values
Console.WriteLine($"int range: {intMin:N0} to {intMax:N0}");
Console.WriteLine($"uint range: {uintMin:N0} to {uintMax:N0}");
Console.ReadKey();
}
}
Output:
int range: -2,147,483,648 to 2,147,483,647
uint range: 0 to 4,294,967,295
Practical Uses of MinValue and MaxValue
// Validation
public bool IsValidYear(int year)
{
return year >= 1900 && year <= DateTime.Now.Year;
}
// Initialize to extreme values
int lowestScore = int.MaxValue; // Start with highest, find lowest
int highestScore = int.MinValue; // Start with lowest, find highest
// Range checking before conversion
long bigNumber = 5000000000L;
if (bigNumber >= int.MinValue && bigNumber <= int.MaxValue)
{
int converted = (int)bigNumber;
}
else
{
Console.WriteLine("Value outside int range!");
}
// Finding min/max in a loop
int[] scores = { 85, 92, 78, 95, 88 };
int min = int.MaxValue;
int max = int.MinValue;
foreach (int score in scores)
{
if (score < min) min = score;
if (score > max) max = score;
}
Nullable Int
By default, value types like int
and uint
cannot be null
. However, you can make them nullable using the ?
syntax.
int regularInt = 10; // Cannot be null
int? nullableInt = null; // Can be null
// Checking for null
if (nullableInt.HasValue)
{
Console.WriteLine($"Value is: {nullableInt.Value}");
}
else
{
Console.WriteLine("No value assigned");
}
// Using null-coalescing operator
int result = nullableInt ?? 0; // Use 0 if null
// Common in database operations
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int? StockQuantity { get; set; } // Null means unknown/not tracked
}
Overflow Behavior
By default, arithmetic operations on int
and uint
do not check for overflow. When a value exceeds the type's range, it wraps around.
// Int overflow
int maxInt = int.MaxValue; // 2,147,483,647
int overflow = maxInt + 1; // -2,147,483,648 (wraps to minimum)
// UInt overflow
uint maxUInt = uint.MaxValue; // 4,294,967,295
uint uintOverflow = maxUInt + 1; // 0 (wraps around)
Checked Context
Enable overflow checking using the checked
keyword to throw exceptions instead of wrapping:
try
{
checked
{
int maxInt = int.MaxValue;
int result = maxInt + 1; // Throws OverflowException
}
}
catch (OverflowException ex)
{
Console.WriteLine("Overflow detected! Value too large.");
}
// Check a specific operation
int result = checked(maxInt + 1);
// Check an entire block
checked
{
int a = int.MaxValue;
int b = 100;
int c = a + b; // Throws OverflowException
}
Unchecked Context
You can explicitly disable overflow checking (though it's the default):
unchecked
{
int maxInt = int.MaxValue;
int result = maxInt + 1; // Wraps around, no exception
}
See Also: Overflow Exception for comprehensive coverage of overflow handling.
Type Conversion
Implicit Conversion (Safe)
int
and uint
can be implicitly converted to larger types:
int myInt = 42;
// Implicit conversions (safe, no data loss)
long myLong = myInt;
float myFloat = myInt;
double myDouble = myInt;
decimal myDecimal = myInt;
// UInt to larger unsigned types
uint myUInt = 100;
ulong myULong = myUInt;
Explicit Conversion (Casting Required)
Converting from larger types or between signed/unsigned requires explicit casting:
long bigNumber = 5000000000L;
int smallNumber = (int)bigNumber; // Data loss! Wraps around
// Safer approach
if (bigNumber >= int.MinValue && bigNumber <= int.MaxValue)
{
int safeConversion = (int)bigNumber;
}
else
{
Console.WriteLine("Value out of int range!");
}
// Converting between signed and unsigned
int signedValue = -10;
uint unsignedValue = (uint)signedValue; // Dangerous! Results in large positive number
uint largeUInt = 3000000000;
int signedFromUInt = (int)largeUInt; // Overflow! Becomes negative
Using Convert and Parse
// String to int
string numberText = "123";
int number = int.Parse(numberText);
// Safe parsing with TryParse (recommended)
if (int.TryParse("456", out int result))
{
Console.WriteLine($"Converted: {result}");
}
else
{
Console.WriteLine("Invalid number format");
}
// Using Convert class
int converted = Convert.ToInt32("789");
uint uintConverted = Convert.ToUInt32("1000");
// Handling different number formats
int hexNumber = Convert.ToInt32("FF", 16); // Hexadecimal
int binaryNumber = Convert.ToInt32("1010", 2); // Binary
Practical Examples
Example 1: Loop Counters
// Most common use of int
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"Iteration: {i}");
}
// Countdown
for (int countdown = 10; countdown > 0; countdown--)
{
Console.WriteLine(countdown);
}
Console.WriteLine("Blast off!");
Example 2: Array Indexing
string[] names = { "Alice", "Bob", "Charlie", "David" };
for (int index = 0; index < names.Length; index++)
{
Console.WriteLine($"{index + 1}. {names[index]}");
}
Example 3: Age Calculation
public class Person
{
public string Name { get; set; }
public int BirthYear { get; set; }
public int GetAge()
{
int currentYear = DateTime.Now.Year;
return currentYear - BirthYear;
}
}
// Usage
Person person = new Person
{
Name = "John",
BirthYear = 1990
};
Console.WriteLine($"{person.Name} is {person.GetAge()} years old");
Example 4: Score Tracking
public class Game
{
private int _score;
private int _highScore;
public int Score
{
get { return _score; }
private set
{
_score = value;
if (_score > _highScore)
{
_highScore = _score;
}
}
}
public int HighScore { get { return _highScore; } }
public void AddPoints(int points)
{
if (points > 0)
{
Score += points;
Console.WriteLine($"Score: {Score} (High: {HighScore})");
}
}
}
Example 5: File Size (UInt)
public class FileInfo
{
public string FileName { get; set; }
public uint SizeInBytes { get; set; }
public string GetReadableSize()
{
if (SizeInBytes < 1024)
return $"{SizeInBytes} bytes";
else if (SizeInBytes < 1024 * 1024)
return $"{SizeInBytes / 1024.0:F2} KB";
else if (SizeInBytes < 1024 * 1024 * 1024)
return $"{SizeInBytes / (1024.0 * 1024):F2} MB";
else
return $"{SizeInBytes / (1024.0 * 1024 * 1024):F2} GB";
}
}
Common Mistakes to Avoid
Mistake 1: Integer Division
int a = 5;
int b = 2;
int result = a / b; // result = 2, not 2.5!
// To get decimal result, cast to double
double decimalResult = (double)a / b; // result = 2.5
Mistake 2: Overflow Without Checking
int count = int.MaxValue;
count++; // Wraps to int.MinValue!
// Better approach
if (count < int.MaxValue)
{
count++;
}
else
{
Console.WriteLine("Cannot increment, at maximum value");
}
Mistake 3: Using UInt Unnecessarily
// Bad - creates casting issues
public uint GetLength()
{
return (uint)myArray.Length; // Length is int, requires cast
}
// Good - use int
public int GetLength()
{
return myArray.Length; // No casting needed
}
Mistake 4: Negative UInt Values
int temperature = -5;
uint unsignedTemp = (uint)temperature; // Becomes 4,294,967,291!
// This is almost never what you want
Console.WriteLine(unsignedTemp); // Prints huge positive number
Performance Considerations
Int vs Long
// Use int when possible - it's faster and uses less memory
int count = 0; // Preferred for most cases
long bigCount = 0; // Only when you need the range
// Int is faster in loops
for (int i = 0; i < 1000000; i++) // Faster
{
// Do work
}
for (long i = 0; i < 1000000; i++) // Slower
{
// Do work
}
Bitwise Operations
// Int is ideal for bit manipulation
int flags = 0;
const int FLAG_READ = 1; // 0001
const int FLAG_WRITE = 2; // 0010
const int FLAG_EXECUTE = 4; // 0100
// Set flags
flags |= FLAG_READ | FLAG_WRITE;
// Check flags
bool canRead = (flags & FLAG_READ) != 0;
bool canWrite = (flags & FLAG_WRITE) != 0;
Key Takeaways
- int is the default choice for integer values in C# (use it 95% of the time)
- uint is for positive-only values when you need the extra range
- Both store 32 bits (4 bytes) of data
- Use lowercase
int
anduint
keywords (not Int32/UInt32) - Be aware of integer division (5 / 2 = 2, not 2.5)
- Watch for overflow when doing arithmetic
- Use
int.MaxValue
andint.MinValue
for boundary checking int?
makes integers nullable for database operations
Next Steps
Explore related integer types and concepts:
- Byte and SByte - 8-bit integers
- Short and UShort - 16-bit integers
- Long and ULong - 64-bit integers
- BigInteger - Arbitrary precision integers
- Overflow Exceptions - Handling numeric overflow