C# Data Types - Complete Guide
Introduction to Data Types
Data types in C# define the kind of values that variables can store. Since C# is a strongly-typed language, every variable must have a declared type. This ensures type safety, improves performance, and makes the code easier to understand.
C# data types are grouped into two main categories: value types and reference types. Value types hold data directly, while reference types hold references (pointers) to the memory location where the data is stored.
Value Types
Value types contain their values directly. When a value type is assigned to another, the value is copied. Examples include numeric types, char, bool, and structs:
using System;
namespace ValueTypesExample
{
class Program
{
static void Main(string[] args)
{
// Integer types
byte byteValue = 255; // 0 to 255 (1 byte)
sbyte sbyteValue = -128; // -128 to 127 (1 byte)
short shortValue = -32768; // -32,768 to 32,767 (2 bytes)
ushort ushortValue = 65535; // 0 to 65,535 (2 bytes)
int intValue = 2147483647; // -2,147,483,648 to 2,147,483,647 (4 bytes)
uint uintValue = 4294967295; // 0 to 4,294,967,295 (4 bytes)
long longValue = 9223372036854775807; // -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (8 bytes)
ulong ulongValue = 18446744073709551615; // 0 to 18,446,744,073,709,551,615 (8 bytes)
// Floating-point types
float floatValue = 3.402823E+38F; // Approx ±1.5 × 10^−45 to ±3.4 × 10^38 (4 bytes)
double doubleValue = 1.7976931348623157E+308; // Approx ±5.0 × 10^−324 to ±1.7 × 10^308 (8 bytes)
decimal decimalValue = 7.9228M; // Approx ±1.0 × 10^−28 to ±7.9 × 10^28 (16 bytes, high precision)
// Other value types
char charValue = 'A'; // Single Unicode character (2 bytes)
bool boolValue = true; // true or false
// Display values
Console.WriteLine($"Byte: {byteValue}");
Console.WriteLine($"Int: {intValue}");
Console.WriteLine($"Float: {floatValue}");
Console.WriteLine($"Double: {doubleValue}");
Console.WriteLine($"Decimal: {decimalValue}");
Console.WriteLine($"Char: {charValue}");
Console.WriteLine($"Bool: {boolValue}");
// Value type behavior (copying)
int original = 10;
int copy = original;
copy = 20;
Console.WriteLine($"Original: {original}, Copy: {copy}");
}
}
}
Byte: 255 Int: 2147483647 Float: 3.402823E+38 Double: 1.7976931348623157E+308 Decimal: 7.9228 Char: A Bool: True Original: 10, Copy: 20
Reference Types
Reference types store references to objects. Assigning one reference type variable to another makes both variables point to the same object in memory:
using System;
namespace ReferenceTypesExample
{
class Program
{
static void Main(string[] args)
{
// String type (reference type but behaves like value for equality)
string string1 = "Hello";
string string2 = string1;
string2 = "World";
Console.WriteLine($"String1: {string1}, String2: {string2}");
// Arrays
int[] array1 = { 1, 2, 3 };
int[] array2 = array1;
array2[0] = 10;
Console.WriteLine($"Array1[0]: {array1[0]}, Array2[0]: {array2[0]}");
// Object type
object obj1 = "Hello Object";
object obj2 = 42;
object obj3 = new DateTime(2023, 10, 15);
Console.WriteLine($"Object1: {obj1}, Object2: {obj2}, Object3: {obj3}");
// Dynamic type
dynamic dynamicValue = "Hello Dynamic";
Console.WriteLine($"Dynamic: {dynamicValue}");
dynamicValue = 100;
Console.WriteLine($"Dynamic: {dynamicValue}");
// Class instance
Person person1 = new Person("John", 25);
Person person2 = person1;
person2.Name = "Jane";
Console.WriteLine($"Person1: {person1.Name}, Person2: {person2.Name}");
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
}
String1: Hello, String2: World Array1[0]: 10, Array2[0]: 10 Object1: Hello Object, Object2: 42, Object3: 10/15/2023 12:00:00 AM Dynamic: Hello Dynamic Dynamic: 100 Person1: Jane, Person2: Jane
Nullable Value Types
Value types normally cannot be null, but C# allows nullable versions using the ? modifier. Nullable types are useful when working with databases or optional values.
using System;
namespace NullableTypesExample
{
class Program
{
static void Main(string[] args)
{
int regularInt = 0;
// int nullInt = null; // Invalid
// Nullable value types
int? nullableInt = null;
double? nullableDouble = 3.14;
bool? nullableBool = null;
DateTime? nullableDate = null;
Console.WriteLine($"Nullable Int: {nullableInt}");
Console.WriteLine($"Nullable Double: {nullableDouble}");
Console.WriteLine($"Nullable Bool: {nullableBool}");
Console.WriteLine($"Nullable Date: {nullableDate}");
// Checking for null
if (nullableInt.HasValue)
Console.WriteLine($"Nullable Int has value: {nullableInt.Value}");
else
Console.WriteLine("Nullable Int is null");
// Null-coalescing operator
int actualInt = nullableInt ?? 100;
Console.WriteLine($"Actual Int: {actualInt}");
// Assign values later
nullableInt = 42;
nullableBool = true;
nullableDate = DateTime.Now;
Console.WriteLine("\nAfter assignment:");
Console.WriteLine($"Nullable Int: {nullableInt}");
Console.WriteLine($"Nullable Bool: {nullableBool}");
Console.WriteLine($"Nullable Date: {nullableDate}");
}
}
}
Nullable Int: Nullable Double: 3.14 Nullable Bool: Nullable Date: Nullable Int is null Actual Int: 100 After assignment: Nullable Int: 42 Nullable Bool: True Nullable Date: 10/15/2023 2:30:45 PM