🔵 C# .NET
C# Complete Cheatsheet
OOP, LINQ, async/await, delegates, events — complete C# .NET reference.
01
Syntax & Types
▼
CSC# basics
using System;
using System.Collections.Generic;
using System.Linq;
class Program {
static void Main(string[] args) {
// Variables
int age = 22;
double pi = 3.14159;
string name = "Ali";
bool active = true;
var items = new List(); // type inferred
// String interpolation
Console.WriteLine($"Hello, {name}! Age: {age}");
Console.WriteLine($"Pi = {pi:F2}"); // format to 2 decimals
// Null safety (C# 8+)
string? nullable = null; // nullable reference type
string safe = nullable ?? "default";
int? maybeInt = null;
int value = maybeInt ?? 0;
string? upper = nullable?.ToUpper(); // null-conditional
// Pattern matching (C# 9+)
object obj = 42;
if (obj is int n && n > 0) Console.WriteLine($"Positive int: {n}");
// Switch expression (C# 8+)
string label = age switch {
< 13 => "child",
< 18 => "teenager",
< 65 => "adult",
_ => "senior"
};
}
}
var
Type inferred at compile time. Still statically typed.
dynamic
Resolved at runtime. Avoid — loses type safety.
record
Immutable data type: record Person(string Name, int Age); (C# 9+)
using
Import namespace OR resource disposal (using var file = ...)
02
OOP Classes
▼
CSClasses and OOP
public class BankAccount {
private decimal balance;
public string Owner { get; private set; } // auto-property
private static int _count = 0;
// Constructor
public BankAccount(string owner, decimal initial = 0) {
Owner = owner;
balance = initial;
_count++;
}
// Properties
public decimal Balance => balance; // read-only computed
public static int Count => _count;
// Methods
public void Deposit(decimal amount) {
if (amount > 0) balance += amount;
}
public bool Withdraw(decimal amount) {
if (amount > 0 && balance >= amount) { balance -= amount; return true; }
return false;
}
// Override ToString
public override string ToString() => $"{Owner}: {balance:C}";
// Operator overloading
public static BankAccount operator +(BankAccount a, BankAccount b)
=> new BankAccount(a.Owner, a.balance + b.balance);
}
// Object initializer
var acc = new BankAccount("Ali") { }; // then init props if public set
// Records (immutable by default, C# 9+)
record Point(double X, double Y);
var p1 = new Point(1.0, 2.0);
var p2 = p1 with { X = 5.0 }; // non-destructive mutation
03
Inheritance & Polymorphism
▼
CSInheritance and polymorphism
// Abstract base class
public abstract class Shape {
public string Color { get; set; } = "black";
public abstract double Area(); // must implement
public virtual string Describe() => $"{Color} shape";
}
public class Circle : Shape {
public double Radius { get; }
public Circle(double radius) => Radius = radius;
public override double Area() => Math.PI * Radius * Radius;
public override string Describe() => $"{base.Describe()}: Circle r={Radius}";
}
public sealed class Square : Shape { // sealed: can't inherit further
public double Side { get; }
public Square(double side) => Side = side;
public override double Area() => Side * Side;
}
// Polymorphism
Shape[] shapes = { new Circle(5), new Square(4) };
foreach (var shape in shapes)
Console.WriteLine($"{shape.Describe()} area={shape.Area():F2}");
// Pattern matching with types (C# 7+)
foreach (var s in shapes) {
string info = s switch {
Circle c => $"Circle radius {c.Radius}",
Square sq => $"Square side {sq.Side}",
_ => "Unknown"
};
}
04
Interfaces & Abstract
▼
CSInterfaces
// Interface definition public interface IRepository{ T? GetById(int id); IEnumerable GetAll(); void Add(T entity); void Update(T entity); void Delete(int id); int Count { get; } // interface can have property declarations } public interface IExportable { byte[] Export(string format); default string GetDefaultFormat() => "json"; // C# 8+ default impl } // Implement multiple interfaces public class UserRepository : IRepository , IExportable { private List _users = new(); public User? GetById(int id) => _users.FirstOrDefault(u => u.Id == id); public IEnumerable GetAll() => _users; public void Add(User user) => _users.Add(user); public void Update(User user) { Delete(user.Id); Add(user); } public void Delete(int id) => _users.RemoveAll(u => u.Id == id); public int Count => _users.Count; public byte[] Export(string format) => System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(_users); } // Dependency injection pattern public class UserService { private readonly IRepository _repo; public UserService(IRepository repo) => _repo = repo; // inject! }
05
Collections & LINQ
▼
CSCollections and LINQ
using System.Collections.Generic; using System.Linq; // Collections var list = new List{ 1, 2, 3, 4, 5 }; list.Add(6); list.Remove(3); list.Sort(); list.Reverse(); var dict = new Dictionary { ["a"] = 1, ["b"] = 2 }; dict["c"] = 3; if (dict.TryGetValue("a", out int val)) Console.WriteLine(val); var set = new HashSet { 1, 2, 3, 2, 1 }; // {1, 2, 3} var queue = new Queue (); queue.Enqueue("first"); queue.Dequeue(); var stack = new Stack (); stack.Push("top"); stack.Pop(); // LINQ — Language Integrated Query var numbers = Enumerable.Range(1, 10); var evens = numbers.Where(n => n % 2 == 0); var squares = numbers.Select(n => n * n); var bigSquares = numbers.Where(n => n > 3).Select(n => n * n).ToList(); var sum = numbers.Sum(); var max = numbers.Max(); var first = numbers.First(n => n > 5); // 6 var sorted = numbers.OrderByDescending(n => n).ThenBy(n => n); var groups = numbers.GroupBy(n => n % 2 == 0 ? "even" : "odd"); bool any = numbers.Any(n => n > 8); bool all = numbers.All(n => n > 0); var flat = lists.SelectMany(l => l); // flatten // LINQ query syntax (SQL-like) var query = from n in numbers where n % 2 == 0 orderby n descending select n * n;
06
Async/Await
▼
CSAsync/Await
using System.Net.Http;
using System.Threading.Tasks;
public class DataService {
private readonly HttpClient _http = new();
// Async method returns Task
public async Task FetchDataAsync(string url) {
try {
var response = await _http.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
} catch (HttpRequestException ex) {
throw new Exception($"Request failed: {ex.Message}", ex);
}
}
// Parallel async operations
public async Task<(string, string)> FetchBothAsync(string url1, string url2) {
var t1 = FetchDataAsync(url1);
var t2 = FetchDataAsync(url2);
await Task.WhenAll(t1, t2);
return (t1.Result, t2.Result);
}
// IAsyncEnumerable — async streaming (C# 8+)
public async IAsyncEnumerable GenerateAsync() {
for (int i = 0; i < 10; i++) {
await Task.Delay(100);
yield return i;
}
}
}
// Usage
await foreach (var item in service.GenerateAsync()) {
Console.WriteLine(item);
}
💡
Always use Async suffix for async methods. Avoid async void (can't be awaited). Use CancellationToken for cancellable operations.
07
Delegates & Events
▼
CSDelegates and Events
// Delegate — type-safe function pointer public delegate int Operation(int a, int b); Operation add = (a, b) => a + b; Operation mul = (a, b) => a * b; Console.WriteLine(add(3, 4)); // 7 // Built-in delegates FuncaddFunc = (a, b) => a + b; Action print = s => Console.WriteLine(s); Predicate isEven = n => n % 2 == 0; // Multicast delegate Action greet = () => Console.Write("Hello "); greet += () => Console.Write("World"); greet += () => Console.WriteLine("!"); greet(); // Hello World! // Events public class Button { public event EventHandler? Clicked; public void Click() => Clicked?.Invoke(this, EventArgs.Empty); } public class Form { public Form() { var btn = new Button(); btn.Clicked += OnButtonClicked; // subscribe btn.Click(); btn.Clicked -= OnButtonClicked; // unsubscribe } private void OnButtonClicked(object? sender, EventArgs e) => Console.WriteLine("Button clicked!"); }
08
Properties & Indexers
▼
CSProperties and Indexers
public class Temperature {
private double _celsius;
// Full property with validation
public double Celsius {
get => _celsius;
set {
if (value < -273.15) throw new ArgumentException("Below absolute zero!");
_celsius = value;
}
}
// Computed property
public double Fahrenheit => _celsius * 9 / 5 + 32;
public double Kelvin => _celsius + 273.15;
// Auto-property with init (C# 9 — immutable after creation)
public string Unit { get; init; } = "Celsius";
}
// Indexer
public class Matrix {
private double[,] _data;
public int Rows { get; }
public int Cols { get; }
public Matrix(int rows, int cols) {
Rows = rows; Cols = cols;
_data = new double[rows, cols];
}
// Indexer
public double this[int row, int col] {
get => _data[row, col];
set => _data[row, col] = value;
}
}
var m = new Matrix(3, 3);
m[0, 0] = 1.0; // uses indexer
09
Exception Handling
▼
CSException handling
// Try-catch-finally
try {
int result = 10 / 0; // DivideByZeroException
string s = null;
int len = s!.Length; // NullReferenceException
} catch (DivideByZeroException ex) {
Console.WriteLine($"Math: {ex.Message}");
} catch (NullReferenceException ex) when (ex.Message.Contains("null")) {
// Exception filter (when clause)
Console.WriteLine("Null reference with filter");
} catch (Exception ex) {
Console.WriteLine($"General: {ex.Message}");
throw; // rethrow preserving stack trace
} finally {
Console.WriteLine("Always runs");
}
// Custom exception
public class InsufficientFundsException : Exception {
public decimal Amount { get; }
public InsufficientFundsException(decimal amount)
: base($"Need ${amount} more") => Amount = amount;
}
// Using (IDisposable — auto close/release)
using var file = File.OpenRead("data.txt");
// file.Dispose() called automatically when scope ends
// Throw expression (C# 7+)
string name = input ?? throw new ArgumentNullException(nameof(input));
10
Mini Quizzes
▼
❓ Quiz 1
What does 'record' do in C# 9+?
C# records create immutable reference types where equality is based on values, not references. record Person(string Name, int Age) auto-generates constructor, properties, Equals, GetHashCode and ToString.
❓ Quiz 2
What is the difference between IEnumerable and IQueryable in LINQ?
IEnumerable: executes in memory (all data loaded first). IQueryable: translates LINQ to SQL — the database does the filtering. Always use IQueryable when querying databases (Entity Framework) to avoid loading everything into memory.