On this page
Variables and Data Types
C# is statically typed. Every variable has a type known at compile time, which catches errors early and enables tooling like IntelliSense.
Basic Types
int age = 30;
double price = 19.99;
decimal salary = 75000.50m; // precise financial calculations
bool isActive = true;
char grade = 'A';
string name = "Alice";
Console.WriteLine($"{name} is {age}, active: {isActive}");
var and Type Inference
var count = 42; // inferred as int
var message = "Hello"; // inferred as string
var items = new List<int> { 1, 2, 3 };
// var list = null; // error: cannot infer from null
Use var when the type is obvious from the right-hand side.
Value vs Reference Types
// Value type — copied on assignment
int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10
// Reference type — shares memory
int[] arr1 = { 1, 2, 3 };
int[] arr2 = arr1;
arr2[0] = 99;
Console.WriteLine(arr1[0]); // 99
Structs are value types; classes, arrays, and strings are reference types.
Type Conversion
// Implicit (safe widening)
int i = 10;
double d = i;
// Explicit (narrowing — may lose data)
double pi = 3.14;
int truncated = (int)pi; // 3
// Parse strings
int parsed = int.Parse("42");
bool ok = int.TryParse("abc", out int result); // false
Nullable Value Types
int? nullableInt = null;
nullableInt = 5;
if (nullableInt.HasValue)
{
Console.WriteLine(nullableInt.Value);
}
// Null-coalescing
int value = nullableInt ?? 0;
Nullable Reference Types
Enable in project file:
<Nullable>enable</Nullable>
string nonNull = "hello";
string? maybeNull = null;
// Compiler warns if you dereference maybeNull without checking
Console.WriteLine(maybeNull?.Length ?? 0);
This feature helps prevent null reference exceptions at compile time.
string vs StringBuilder
// Concatenation in a loop — slow (creates many string objects)
string result = "";
for (int i = 0; i < 1000; i++)
result += i;
// StringBuilder — efficient for many mutations
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
sb.Append(i);
string built = sb.ToString();
Records (C# 9+)
public record Point(int X, int Y);
public record Person(string Name, int Age);
var p1 = new Point(1, 2);
var p2 = p1 with { X = 10 }; // non-destructive mutation
Console.WriteLine(p1 == p2); // false — value equality
Records provide built-in equality, ToString(), and with expressions.
Pattern Matching on Types
object obj = "hello";
string message = obj switch
{
int n => $"Number: {n}",
string s => $"String: {s}",
_ => "Unknown"
};
Constants vs readonly
public const int MaxRetries = 3; // compile-time constant
public static readonly DateTime AppStart = DateTime.UtcNow; // runtime
Use const for true constants; readonly for values set once at runtime.
Common Pitfalls
- Floating-point equality:
0.1 + 0.2 != 0.3— usedecimalfor money. - Boxing value types into
objectcauses allocations — prefer generics. - Nullable reference warnings ignored — fix them instead of suppressing globally.