.NET C# Data Types
Introduction
Data types are one of the most fundamental concepts in any programming language, and C# is no exception. Data types define the kind of data that a variable can hold, how much memory it occupies, and what operations can be performed on it.
In C#, being a strongly-typed language, every variable must be declared with a specific type before it can be used. This helps prevent errors and makes your code more reliable and easier to understand.
In this guide, we'll explore the various data types available in C#, from the basic primitive types to more complex reference types, and learn how to use them effectively in your programs.
Value Types vs Reference Types
Before diving into specific types, it's important to understand that C# data types are categorized into two main groups:
Value Types
- Stored directly in memory where they are declared
- Each variable has its own copy of the data
- Includes all numeric types,
bool
,char
, andstruct
- Allocated on the stack (usually)
Reference Types
- Store references to the actual data, not the data itself
- Multiple variables can reference the same data
- Includes
string
, arrays, classes, interfaces, and delegates - Allocated on the heap
Primitive Data Types
C# provides several built-in primitive types that map to types in the .NET Framework. Here are the most commonly used ones:
Integer Types
Integer types store whole numbers without decimal points.
Type | Size | Range | Usage |
---|---|---|---|
byte | 1 byte | 0 to 255 | Small unsigned integers |
sbyte | 1 byte | -128 to 127 | Small signed integers |
short | 2 bytes | -32,768 to 32,767 | Medium-range integers |
ushort | 2 bytes | 0 to 65,535 | Medium-range unsigned integers |
int | 4 bytes | -2.1B to 2.1B | Default choice for integers |
uint | 4 bytes | 0 to 4.2B | Larger unsigned integers |
long | 8 bytes | -9.2E+18 to 9.2E+18 | Very large integers |
ulong | 8 bytes | 0 to 18.4E+18 | Very large unsigned integers |
// Integer type examples
byte smallNumber = 255;
int populationCount = 37_500_000; // Underscores can be used for readability
long worldPopulation = 7_900_000_000L; // 'L' suffix for long literals
Console.WriteLine($"Small number: {smallNumber}");
Console.WriteLine($"Population count: {populationCount}");
Console.WriteLine($"World population: {worldPopulation}");
Output:
Small number: 255
Population count: 37500000
World population: 7900000000
Floating-Point Types
For numbers with decimal points:
Type | Size | Precision | Usage |
---|---|---|---|
float | 4 bytes | ~7 digits | When memory is critical, less precision |
double | 8 bytes | ~15-16 digits | Default for decimals, good precision |
decimal | 16 bytes | 28-29 digits | Financial calculations, high precision |
// Floating-point examples
float simpleFloat = 3.14f; // 'f' suffix for float literals
double pi = 3.14159265359; // Default for decimal literals
decimal moneyAmount = 1234.56m; // 'm' suffix for decimal literals
Console.WriteLine($"Simple float: {simpleFloat}");
Console.WriteLine($"PI: {pi}");
Console.WriteLine($"Money amount: {moneyAmount:C}"); // 'C' for currency format
Output:
Simple float: 3.14
PI: 3.14159265359
Money amount: $1,234.56
Other Common Value Types
// Boolean - true or false
bool isActive = true;
bool hasPermission = false;
// Character - single Unicode character
char grade = 'A';
char symbol = '*';
Console.WriteLine($"Is active: {isActive}");
Console.WriteLine($"Grade: {grade}");
Output:
Is active: True
Grade: A
Reference Types
String
Strings in C# represent sequences of characters and are immutable (cannot be changed after creation).
// String examples
string greeting = "Hello, World!";
string emptyString = string.Empty; // Preferred over ""
string nullString = null; // Can be null
// String concatenation
string firstName = "John";
string lastName = "Doe";
string fullName = firstName + " " + lastName;
// String interpolation (recommended)
string message = $"Welcome, {fullName}!";
Console.WriteLine(greeting);
Console.WriteLine(message);
// String methods
Console.WriteLine($"Length: {greeting.Length}");
Console.WriteLine($"Uppercase: {greeting.ToUpper()}");
Console.WriteLine($"Contains 'World': {greeting.Contains("World")}");
Output:
Hello, World!
Welcome, John Doe!
Length: 13
Uppercase: HELLO, WORLD!
Contains 'World': True
Arrays
Arrays store collections of elements of the same type.
// Array declaration and initialization
int[] numbers = new int[5]; // Array of 5 integers, all initialized to 0
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
// Alternative initialization
string[] fruits = new string[] { "Apple", "Banana", "Orange" };
// Or more concisely
string[] colors = { "Red", "Green", "Blue" };
// Accessing arrays
Console.WriteLine($"First number: {numbers[0]}");
Console.WriteLine($"Second fruit: {fruits[1]}");
// Array properties and methods
Console.WriteLine($"Array length: {numbers.Length}");
// Iterating through an array
Console.WriteLine("All colors:");
foreach (string color in colors)
{
Console.WriteLine(color);
}
Output:
First number: 10
Second fruit: Banana
Array length: 5
All colors:
Red
Green
Blue
Type Conversion
C# provides several ways to convert between data types:
Implicit Conversion
Occurs when the target type can safely represent all values of the source type.
// Implicit conversion examples
int intValue = 100;
long longValue = intValue; // int can be implicitly converted to long
float floatValue = intValue; // int can be implicitly converted to float
Console.WriteLine($"Long value: {longValue}");
Console.WriteLine($"Float value: {floatValue}");
Output:
Long value: 100
Float value: 100
Explicit Conversion (Casting)
Required when data loss might occur or when converting between incompatible types.
// Explicit conversion examples
double doubleValue = 123.456;
int intValue = (int)doubleValue; // Explicit cast, decimal part is truncated
long longNumber = 1234L;
int intNumber = (int)longNumber; // Potential data loss if longNumber > int.MaxValue
Console.WriteLine($"Double value: {doubleValue}");
Console.WriteLine($"Converted to int: {intValue}");
Output:
Double value: 123.456
Converted to int: 123
Conversion Methods
The Convert
class and Parse
methods provide additional conversion options.
// Converting string to numeric types
string numberString = "123";
int parsedInt = int.Parse(numberString);
int convertedInt = Convert.ToInt32(numberString);
// TryParse - safer way to parse strings (avoids exceptions)
string potentialNumber = "456";
if (int.TryParse(potentialNumber, out int result))
{
Console.WriteLine($"Successfully parsed: {result}");
}
else
{
Console.WriteLine("Failed to parse");
}
// Convert between numeric types
int intVal = 42;
double doubleVal = Convert.ToDouble(intVal);
Console.WriteLine($"Converted to double: {doubleVal}");
Output:
Successfully parsed: 456
Converted to double: 42
Nullable Types
Value types normally cannot hold null values. Nullable types enable value types to have an additional null
state.
// Nullable types
int? nullableInt = null;
double? nullableDouble = 3.14;
// Testing for null
if (nullableInt.HasValue)
{
Console.WriteLine($"Value: {nullableInt.Value}");
}
else
{
Console.WriteLine("nullableInt is null");
}
// Null-coalescing operator
int definiteInt = nullableInt ?? 0; // If nullableInt is null, use 0
Console.WriteLine($"definiteInt: {definiteInt}");
// Null-conditional operator
Console.WriteLine($"Value or default: {nullableDouble?.ToString() ?? "No value"}");
Output:
nullableInt is null
definiteInt: 0
Value or default: 3.14
Real-World Examples
Building a Simple Calculator
// Simple calculator example
double num1 = 15.5;
double num2 = 3.0;
double sum = num1 + num2;
double difference = num1 - num2;
double product = num1 * num2;
double quotient = num1 / num2;
Console.WriteLine("Calculator Results:");
Console.WriteLine($"{num1} + {num2} = {sum}");
Console.WriteLine($"{num1} - {num2} = {difference}");
Console.WriteLine($"{num1} * {num2} = {product}");
Console.WriteLine($"{num1} / {num2} = {quotient}");
Output:
Calculator Results:
15.5 + 3 = 18.5
15.5 - 3 = 12.5
15.5 * 3 = 46.5
15.5 / 3 = 5.166666666666667
Managing Product Inventory
// Product inventory example
string productName = "Laptop";
int quantity = 10;
decimal price = 999.99m;
bool isInStock = true;
// Calculate inventory value
decimal inventoryValue = quantity * price;
// Format currency output
string formattedPrice = price.ToString("C");
string formattedInventoryValue = inventoryValue.ToString("C");
Console.WriteLine("Product Information:");
Console.WriteLine($"Name: {productName}");
Console.WriteLine($"Price: {formattedPrice}");
Console.WriteLine($"In Stock: {isInStock}");
Console.WriteLine($"Quantity: {quantity}");
Console.WriteLine($"Total Value: {formattedInventoryValue}");
Output:
Product Information:
Name: Laptop
Price: $999.99
In Stock: True
Quantity: 10
Total Value: $9,999.90
Advanced Type Concepts
Constants
Constants are immutable values whose values are known at compile time.
// Constant examples
const double PI = 3.14159265359;
const string APP_NAME = "MyApplication";
const int MAX_USERS = 1000;
Console.WriteLine($"Application: {APP_NAME}");
Console.WriteLine($"PI value: {PI}");
Output:
Application: MyApplication
PI value: 3.14159265359
Enumerations
Enums define a set of named constants for a specific purpose.
// Enum definition
enum Days
{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
}
// Using enums
Days today = Days.Wednesday;
Console.WriteLine($"Today is {today}");
// Enums with specific values
enum UserRole
{
Guest = 1,
Member = 2,
Moderator = 3,
Administrator = 4
}
UserRole role = UserRole.Member;
Console.WriteLine($"User role: {role} (value: {(int)role})");
// Checking enum values
if (role == UserRole.Administrator)
{
Console.WriteLine("User has admin privileges");
}
else
{
Console.WriteLine("User has limited privileges");
}
Output:
Today is Wednesday
User role: Member (value: 2)
User has limited privileges
Summary
In this guide, we've explored the various data types available in C#:
- Value types: Including primitive numeric types (
int
,double
, etc.),bool
, andchar
- Reference types: Such as
string
, arrays, and objects - Type conversion: Both implicit and explicit, along with conversion methods
- Nullable types: For representing value types that can be null
- Advanced types: Including constants and enumerations
Understanding data types is crucial for writing efficient and error-free C# code. Proper data type selection helps optimize memory usage, improves code readability, and prevents potential errors during runtime.
Exercises
- Create a program that demonstrates using different numeric types to calculate areas of geometric shapes.
- Write a string manipulation program that counts vowels, reverses text, and converts between uppercase and lowercase.
- Create an inventory management system that uses arrays to store product information.
- Write a program that demonstrates type conversion between different data types.
- Create an enum for different file types and write code that processes files differently based on type.
Additional Resources
- Microsoft C# Documentation on Types
- C# Type Conversion
- Working with Nullable Types
- C# Enumerations Documentation
By mastering C# data types, you'll have established one of the key foundational skills needed for .NET development. This knowledge will serve as a building block for more advanced C# topics and application development.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)