C# Basics
C#
using System;
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
// Output
Console.WriteLine("Hello, World!");
// Variables
int age = 25;
double salary = 50000.50;
string name = "Alice";
bool isActive = true;
char grade = 'A';
// var - Implicit typing
var count = 10; // int
var price = 99.99; // double
// Constants
const int MAX_SIZE = 100;
// Nullable types
int? nullableInt = null;
nullableInt = 5;
// Null coalescing
int value = nullableInt ?? 0;
// Input
Console.Write("Enter your name: ");
string input = Console.ReadLine();
// String interpolation
Console.WriteLine($"Hello, {name}! Age: {age}");
// Type conversion
int num = int.Parse("42");
int.TryParse("123", out int result);
string str = age.ToString();
}
}
}
Control Flow
C#
// if-else
if (age >= 18)
Console.WriteLine("Adult");
else if (age >= 13)
Console.WriteLine("Teen");
else
Console.WriteLine("Child");
// Switch (traditional)
switch (grade)
{
case 'A':
Console.WriteLine("Excellent!");
break;
case 'B':
Console.WriteLine("Good!");
break;
default:
Console.WriteLine("Try harder!");
break;
}
// Switch expression (C# 8+)
string result = grade switch
{
'A' => "Excellent!",
'B' => "Good!",
_ => "Try harder!"
};
// for loop
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
// foreach
string[] names = { "Alice", "Bob", "Charlie" };
foreach (string n in names)
{
Console.WriteLine(n);
}
// while
int count = 0;
while (count < 5)
{
Console.WriteLine(count++);
}
Object-Oriented Programming
C#
// Class definition
public class Person
{
// Fields (private by default)
private string _name;
private int _age;
// Auto-implemented property
public string Email { get; set; }
// Property with backing field
public string Name
{
get => _name;
set => _name = value ?? "Unknown";
}
// Read-only property
public int Age
{
get => _age;
private set => _age = value >= 0 ? value : 0;
}
// Constructor
public Person(string name, int age)
{
Name = name;
Age = age;
}
// Method
public void Introduce()
{
Console.WriteLine($"Hi, I'm {Name}, {Age} years old.");
}
// Static member
public static int Count { get; private set; } = 0;
}
// Inheritance
public class Employee : Person
{
public decimal Salary { get; set; }
public Employee(string name, int age, decimal salary)
: base(name, age)
{
Salary = salary;
}
// Override
public override string ToString()
{
return $"{Name} - ${Salary}";
}
}
// Interface
public interface IWorkable
{
void Work();
string JobTitle { get; set; }
}
// Abstract class
public abstract class Shape
{
public abstract double Area();
public virtual void Draw() => Console.WriteLine("Drawing shape");
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double Area() => Math.PI * Radius * Radius;
public override void Draw() => Console.WriteLine("Drawing circle");
}
Collections
C#
using System.Collections.Generic;
// Arrays
int[] numbers = { 1, 2, 3, 4, 5 };
int[] nums = new int[5];
string[,] matrix = new string[3, 3];
// List - Dynamic array
List<int> list = new List<int> { 1, 2, 3 };
list.Add(4);
list.Remove(2);
list.Insert(0, 0);
list.RemoveAt(0);
bool exists = list.Contains(3);
int count = list.Count;
// Dictionary - Key-value pairs
Dictionary<string, int> ages = new Dictionary<string, int>
{
{ "Alice", 25 },
{ "Bob", 30 }
};
ages["Charlie"] = 35;
ages.TryGetValue("Alice", out int age);
foreach (var kvp in ages)
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
// HashSet - Unique elements
HashSet<int> set = new HashSet<int> { 1, 2, 3, 3 }; // {1, 2, 3}
set.Add(4);
set.Remove(1);
bool contains = set.Contains(2);
// Queue - FIFO
Queue<string> queue = new Queue<string>();
queue.Enqueue("First");
queue.Enqueue("Second");
string first = queue.Dequeue(); // "First"
string peek = queue.Peek(); // "Second"
// Stack - LIFO
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
int top = stack.Pop(); // 2
int look = stack.Peek(); // 1
LINQ (Language Integrated Query)
C#
using System.Linq;
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Where - Filter
var evens = numbers.Where(n => n % 2 == 0);
// Select - Transform
var doubled = numbers.Select(n => n * 2);
// OrderBy / OrderByDescending
var sorted = numbers.OrderBy(n => n);
var descending = numbers.OrderByDescending(n => n);
// First / Last / Single
int first = numbers.First();
int last = numbers.Last();
int firstEven = numbers.First(n => n % 2 == 0);
int firstOrDefault = numbers.FirstOrDefault(n => n > 100); // 0
// Any / All
bool hasEvens = numbers.Any(n => n % 2 == 0); // true
bool allPositive = numbers.All(n => n > 0); // true
// Count / Sum / Average / Max / Min
int count = numbers.Count();
int sum = numbers.Sum();
double avg = numbers.Average();
int max = numbers.Max();
// Take / Skip
var firstThree = numbers.Take(3); // 1, 2, 3
var skipThree = numbers.Skip(3); // 4, 5, 6, ...
// Distinct
var unique = numbers.Distinct();
// GroupBy
var grouped = numbers.GroupBy(n => n % 2 == 0 ? "Even" : "Odd");
// Query syntax (alternative)
var query = from n in numbers
where n > 5
orderby n descending
select n * 2;
// ToList / ToArray / ToDictionary
List<int> list = numbers.Where(n => n > 5).ToList();
int[] array = numbers.ToArray();
Dictionary<int, int> dict = numbers.ToDictionary(n => n, n => n * n);
Async/Await
C#
using System.Threading.Tasks;
using System.Net.Http;
// Async method
public async Task<string> GetDataAsync(string url)
{
using HttpClient client = new HttpClient();
string result = await client.GetStringAsync(url);
return result;
}
// Async void (only for event handlers)
public async void ButtonClick(object sender, EventArgs e)
{
await DoSomethingAsync();
}
// Task.Run for CPU-bound work
public async Task ProcessDataAsync()
{
int result = await Task.Run(() =>
{
// Heavy computation
return ExpensiveCalculation();
});
}
// Multiple tasks
public async Task ProcessMultipleAsync()
{
Task<string> task1 = GetDataAsync("url1");
Task<string> task2 = GetDataAsync("url2");
// Wait for all
await Task.WhenAll(task1, task2);
// Or wait for any
Task<string> first = await Task.WhenAny(task1, task2);
}
// Cancellation
public async Task CancellableMethodAsync(CancellationToken token)
{
for (int i = 0; i < 100; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
}
}
// Usage
var cts = new CancellationTokenSource();
cts.CancelAfter(5000); // Cancel after 5 seconds
try
{
await CancellableMethodAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation was cancelled");
}
Delegates & Events
C#
// Delegate declaration
public delegate int MathOperation(int a, int b);
// Using delegate
MathOperation add = (a, b) => a + b;
MathOperation multiply = (a, b) => a * b;
int result = add(3, 5); // 8
// Built-in delegates
Func<int, int, int> subtract = (a, b) => a - b; // Returns value
Action<string> print = msg => Console.WriteLine(msg); // No return
Predicate<int> isEven = n => n % 2 == 0; // Returns bool
// Events
public class Button
{
public event EventHandler Clicked;
public void Click()
{
Clicked?.Invoke(this, EventArgs.Empty);
}
}
// Custom event args
public class DataEventArgs : EventArgs
{
public string Data { get; set; }
}
public class DataProcessor
{
public event EventHandler<DataEventArgs> DataProcessed;
protected virtual void OnDataProcessed(string data)
{
DataProcessed?.Invoke(this, new DataEventArgs { Data = data });
}
public void Process()
{
// Processing...
OnDataProcessed("Processed data");
}
}
// Subscribe to events
var processor = new DataProcessor();
processor.DataProcessed += (sender, e) =>
{
Console.WriteLine($"Data: {e.Data}");
};
Modern C# Features
C#
// Records (C# 9+) - Immutable data types
public record Person(string Name, int Age);
var p1 = new Person("Alice", 25);
var p2 = p1 with { Age = 26 }; // Non-destructive mutation
// Init-only properties
public class Config
{
public string Setting { get; init; }
}
// Pattern matching
object obj = 42;
if (obj is int n && n > 0)
{
Console.WriteLine($"Positive int: {n}");
}
// Switch expression with patterns
string GetDescription(object obj) => obj switch
{
int i when i > 0 => "Positive",
int i when i < 0 => "Negative",
int => "Zero",
string s => $"String: {s}",
null => "Null",
_ => "Unknown"
};
// Null-conditional operators
string name = person?.Name;
int? length = person?.Name?.Length;
// Null-coalescing assignment (C# 8+)
list ??= new List<int>();
// Target-typed new (C# 9+)
List<int> numbers = new();
Dictionary<string, int> dict = new();
// Top-level statements (C# 9+)
// Program.cs can be just:
Console.WriteLine("Hello, World!");
// Global usings (C# 10+)
// global using System.Collections.Generic;
// File-scoped namespace (C# 10+)
// namespace MyApp;
// Raw string literals (C# 11+)
var json = """
{
"name": "Alice",
"age": 25
}
""";
C# Best Practices:
• Use var when type is obvious
• Prefer async/await for I/O operations
• Use records for DTOs
• Handle nulls with ?. and ??
• Use LINQ for collections
• Use var when type is obvious
• Prefer async/await for I/O operations
• Use records for DTOs
• Handle nulls with ?. and ??
• Use LINQ for collections