Skip to content

Latest commit

 

History

History
1506 lines (1260 loc) · 35.7 KB

File metadata and controls

1506 lines (1260 loc) · 35.7 KB

CSharp COMPREHENSIVE CHEATSHEET

Complete reference covering syntax, types, OOP, LINQ, async/await, collections, exceptions, file I/O, pattern matching, records, and more. Includes 24 sections with practical examples.

📑 TABLE OF CONTENTS

  1. Basic Syntax & Data Types
  2. Variables & Constants
  3. Type Conversion & Casting
  4. Operators
  5. Strings
  6. Arrays & Collections
  7. Control Flow
  8. Loops
  9. Methods
  10. Classes & OOP
  11. Inheritance & Polymorphism
  12. Interfaces & Abstract Classes
  13. Properties & Indexers
  14. Structs & Enums
  15. Exception Handling
  16. Delegates & Events
  17. LINQ
  18. File I/O
  19. Asynchronous Programming
  20. Attributes & Reflection
  21. Nullable Types & Null Safety
  22. Records (C# 9+)
  23. Pattern Matching (C# 7-11)
  24. Top-Level Statements (C# 9+)

1. BASIC SYNTAX & DATA TYPES

// Hello World
using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}

// Value Types (stored on stack)
bool flag = true;           // System.Boolean
byte b = 255;               // 0-255
sbyte sb = -128;            // -128 to 127
short sh = 32767;           // -32,768 to 32,767
ushort ush = 65535;         // 0-65,535
int i = 2147483647;         // Most common integer
uint ui = 4294967295;       // Unsigned int
long l = 9223372036854775807;
ulong ul = 18446744073709551615;
float f = 3.14f;            // 32-bit, suffix f
double d = 3.14159;         // 64-bit, default
decimal m = 19.95m;         // 128-bit, for money, suffix m
char c = 'A';               // Unicode character

// Reference Types (stored on heap)
string name = "John";       // Immutable string
object obj = 123;           // Base type of all types
dynamic dyn = 123;          // Runtime type checking

2. VARIABLES & CONSTANTS

// Declaration & Initialization
int age;                    // Declaration
age = 25;                   // Assignment
int score = 100;            // Declaration + initialization
var inferred = "Hello";     // Implicitly typed

// Constants
const double PI = 3.14159;  // Compile-time constant
readonly int MAX_USERS;      // Runtime constant (can be set in constructor)

// Variable scope
{
    int blockScoped = 10;   // Only accessible inside this block
}

3. TYPE CONVERSION & CASTING

// Implicit casting (safe, no data loss)
int num = 100;
double dnum = num;          // int to double

// Explicit casting (may lose data)
double pi = 3.14;
int intPi = (int)pi;        // 3 (truncated)

// Using Convert class
string numStr = "123";
int parsed = Convert.ToInt32(numStr);
double fromInt = Convert.ToDouble(42);
bool fromString = Convert.ToBoolean("true");

// Parse and TryParse
int result = int.Parse("456");
bool success = int.TryParse("789", out int safeResult);

// Boxing & Unboxing
object boxed = 42;          // Boxing (value → reference)
int unboxed = (int)boxed;   // Unboxing (reference → value)

4. OPERATORS

// Arithmetic: + - * / % ++ --
int sum = 5 + 3;            // 8
int diff = 10 - 4;          // 6
int product = 6 * 7;        // 42
int quotient = 20 / 3;      // 6 (integer division)
int remainder = 20 % 3;     // 2
int counter = 5;
counter++;                  // Increment (post)
++counter;                  // Increment (pre)

// Comparison: == != < > <= >=
bool isEqual = (5 == 5);    // true
bool isNotEqual = (5 != 3); // true
bool isGreater = (10 > 5);  // true

// Logical: && || !
bool andResult = true && false;   // false
bool orResult = true || false;    // true
bool notResult = !true;           // false

// Ternary operator
int max = (a > b) ? a : b;

// Null-coalescing
string name = null;
string display = name ?? "Guest"; // "Guest"

// Null-conditional
int? length = name?.Length;       // null if name is null

// Bitwise: & | ^ ~ << >>
int bitAnd = 5 & 3;       // 1 (0101 & 0011 = 0001)
int bitOr = 5 | 3;        // 7 (0101 | 0011 = 0111)
int leftShift = 5 << 1;   // 10 (0101 → 1010)

5. STRINGS

// String declaration
string s1 = "Hello";
string s2 = @"C:\MyFolder\file.txt";     // Verbatim string
string s3 = $"Hello, {name}!";            // String interpolation
string s4 = @"He said, ""Hello""";        // Escape quotes

// Common methods
string str = "  Hello World  ";
str.Length;                 // Length property
str.ToUpper();              // "  HELLO WORLD  "
str.ToLower();              // "  hello world  "
str.Trim();                 // "Hello World"
str.TrimStart();            // "Hello World  "
str.TrimEnd();              // "  Hello World"
str.Substring(2, 5);        // "Hello"
str.Replace("World", "C#"); // "  Hello C#  "
str.Contains("Hello");      // true
str.StartsWith("  He");     // true
str.EndsWith("ld  ");       // true
str.IndexOf("World");       // 7
str.LastIndexOf("o");       // 9
string[] parts = str.Split(' ');

// String concatenation
string combined = "Hello" + " " + "World";
combined = string.Concat("Hello", " ", "World");
combined = string.Join(", ", new[] { "A", "B", "C" });

// StringBuilder (for performance)
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("Hello");
sb.AppendLine(" World");
sb.AppendFormat("Number: {0}", 42);
string result = sb.ToString();

// String interpolation
int x = 10, y = 20;
string sum = $"{x} + {y} = {x + y}";  // "10 + 20 = 30"

6. ARRAYS & COLLECTIONS

// Arrays
int[] numbers = new int[5];              // Array of 5 ints
int[] initialized = { 1, 2, 3, 4, 5 };   // Initializer
int[][] jagged = new int[3][];           // Jagged array
jagged[0] = new int[] { 1, 2 };
int[,] multiDim = new int[3, 4];         // 2D array

numbers[0] = 10;                         // Access element
int first = numbers[0];
int arrayLength = numbers.Length;

// Array methods
Array.Sort(initialized);
Array.Reverse(initialized);
Array.IndexOf(initialized, 3);           // Returns index or -1

// List<T>
using System.Collections.Generic;
List<int> list = new List<int>();
list.Add(1);
list.AddRange(new[] { 2, 3, 4 });
list.Insert(0, 0);                       // Insert at index
list.Remove(2);                          // Remove by value
list.RemoveAt(1);                        // Remove by index
bool contains = list.Contains(3);
int index = list.IndexOf(4);
list.Sort();
list.Reverse();
list.Clear();
int count = list.Count;

// Dictionary<TKey, TValue>
Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("Alice", 30);
ages["Bob"] = 25;                        // Add or update
int aliceAge = ages["Alice"];
ages.ContainsKey("Charlie");             // false
ages.TryGetValue("Bob", out int bobAge); // Returns bool
foreach(var kvp in ages) {
    Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}

// Other collections
HashSet<int> set = new HashSet<int>();   // Unique values
Queue<string> queue = new Queue<string>();
queue.Enqueue("First");
string dequeued = queue.Dequeue();
Stack<int> stack = new Stack<int>();
stack.Push(1);
int popped = stack.Pop();

// Immutable arrays (LINQ)
var squares = numbers.Select(x => x * x).ToArray();

7. CONTROL FLOW

// If-else
if (condition)
{
    // code
}
else if (anotherCondition)
{
    // code
}
else
{
    // code
}

// Switch (traditional)
int day = 3;
switch (day)
{
    case 1:
        Console.WriteLine("Monday");
        break;
    case 2:
    case 3:
        Console.WriteLine("Tuesday or Wednesday");
        break;
    default:
        Console.WriteLine("Other");
        break;
}

// Switch expression (C# 8+)
string result = day switch
{
    1 => "Monday",
    2 => "Tuesday",
    3 => "Wednesday",
    _ => "Other"
};

// Switch with patterns (C# 7+)
object obj = 42;
string typeName = obj switch
{
    int i when i > 0 => "Positive int",
    int i => "Int",
    string s => $"String: {s}",
    null => "Null",
    _ => "Unknown"
};

8. LOOPS

// For loop
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(i);
}

// Foreach loop
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (int num in numbers)
{
    Console.WriteLine(num);
}

// While loop
int count = 0;
while (count < 5)
{
    Console.WriteLine(count);
    count++;
}

// Do-while (executes at least once)
int x = 10;
do
{
    Console.WriteLine(x);
    x++;
} while (x < 5);

// Loop control
break;      // Exit loop immediately
continue;   // Skip to next iteration
return;     // Exit method
goto label; // Jump to labeled statement (avoid if possible)

9. METHODS

// Basic method
public int Add(int a, int b)
{
    return a + b;
}

// Void method
public void Greet(string name)
{
    Console.WriteLine($"Hello, {name}");
}

// Optional parameters
public void Log(string message, string prefix = "INFO")
{
    Console.WriteLine($"[{prefix}] {message}");
}

// Named arguments
Log(message: "Started", prefix: "DEBUG");

// Reference parameters (ref)
public void Increment(ref int value)
{
    value++;
}
int num = 5;
Increment(ref num);  // num is now 6

// Output parameters (out)
public bool TryDivide(int a, int b, out int result)
{
    if (b != 0)
    {
        result = a / b;
        return true;
    }
    result = 0;
    return false;
}

// In parameter (read-only reference)
public void Display(in int value)
{
    // Cannot modify value
    Console.WriteLine(value);
}

// Params keyword (variable arguments)
public int Sum(params int[] numbers)
{
    return numbers.Sum();
}
int total = Sum(1, 2, 3, 4, 5);

// Method overloading
public int Multiply(int a, int b) => a * b;
public double Multiply(double a, double b) => a * b;

// Local functions
int OuterMethod()
{
    int LocalFunction(int x) => x * 2;
    return LocalFunction(5);
}

// Expression-bodied member
public int Square(int x) => x * x;

10. CLASSES & OOP

// Basic class
public class Person
{
    // Fields (private by convention)
    private string _name;
    private int _age;
    
    // Constructor
    public Person(string name, int age)
    {
        _name = name;
        _age = age;
    }
    
    // Default constructor (auto-implemented if no constructors)
    public Person() { }
    
    // Constructor chaining
    public Person(string name) : this(name, 0) { }
    
    // Methods
    public void Introduce()
    {
        Console.WriteLine($"I'm {_name}, {_age} years old");
    }
    
    // Static method
    public static void SayHello()
    {
        Console.WriteLine("Hello!");
    }
    
    // Destructor (rarely used)
    ~Person()
    {
        // Cleanup code
    }
}

// Access modifiers
// public        - Any code can access
// private       - Only within the same class
// protected     - Within class and derived classes
// internal      - Within same assembly
// protected internal - Same assembly or derived classes
// private protected - Same assembly AND derived classes

// Using the class
Person john = new Person("John", 30);
john.Introduce();
Person.SayHello();

11. INHERITANCE & POLYMORPHISM

// Base class
public class Animal
{
    public string Name { get; set; }
    
    public virtual void MakeSound()  // Virtual allows override
    {
        Console.WriteLine("Some sound");
    }
    
    public void Eat()
    {
        Console.WriteLine("Eating...");
    }
}

// Derived class
public class Dog : Animal
{
    public string Breed { get; set; }
    
    public override void MakeSound()  // Override virtual method
    {
        Console.WriteLine("Woof!");
    }
    
    public new void Eat()  // Hide base method (rarely used)
    {
        Console.WriteLine("Dog eating...");
    }
}

// Sealed class (cannot be inherited from)
public sealed class MathHelper
{
    // methods
}

// Polymorphism
Animal myDog = new Dog();
myDog.MakeSound();  // Calls Dog's MakeSound() (polymorphic)

// Type checking
if (myDog is Dog)
{
    Dog d = (Dog)myDog;  // Explicit cast
}

Dog d2 = myDog as Dog;  // Safe cast (null if fails)
if (d2 != null) { }

// Calling base constructor
public class Cat : Animal
{
    public Cat(string name) : base()  // Call base constructor
    {
        Name = name;
    }
    
    protected override void MakeSound()  // Protected override
    {
        base.MakeSound();  // Call base implementation
        Console.WriteLine("Meow!");
    }
}

12. INTERFACES & ABSTRACT CLASSES

// Interface (contract)
public interface IPrintable
{
    void Print();                    // No implementation
    string Name { get; set; }       // Property
}

// Interface with default implementation (C# 8+)
public interface ILogger
{
    void Log(string message);
    void LogError(string error)      // Default implementation
    {
        Log($"ERROR: {error}");
    }
}

// Multiple interface implementation
public class Document : IPrintable, ILogger
{
    public string Name { get; set; }
    
    public void Print()
    {
        Console.WriteLine($"Printing {Name}");
    }
    
    public void Log(string message)
    {
        Console.WriteLine($"Log: {message}");
    }
}

// Abstract class (partial implementation)
public abstract class Shape
{
    public abstract double GetArea();  // Must be implemented
    
    public virtual string GetColor()    // Optional override
    {
        return "Red";
    }
    
    public void Display()               // Concrete method
    {
        Console.WriteLine($"Area: {GetArea()}");
    }
}

public class Circle : Shape
{
    public double Radius { get; set; }
    
    public override double GetArea()
    {
        return Math.PI * Radius * Radius;
    }
}

13. PROPERTIES & INDEXERS

// Auto-implemented property
public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// Full property with backing field
public class Customer
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set 
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentException("Name cannot be empty");
            _name = value;
        }
    }
}

// Read-only property
public class Settings
{
    public static string AppName { get; } = "MyApp";
}

// Computed property
public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }
    public double Area => Width * Height;  // Expression-bodied
}

// Init-only property (C# 9+)
public class Person
{
    public string Name { get; init; }  // Can only be set during initialization
}
var p = new Person { Name = "Alice" };  // OK
// p.Name = "Bob";  // Error!

// Required properties (C# 11+)
public class Employee
{
    public required int Id { get; set; }
    public required string Name { get; set; }
}
// var e = new Employee { Name = "John" };  // Error: Id missing

// Indexers
public class ShoppingCart
{
    private List<Product> _products = new List<Product>();
    
    public Product this[int index]
    {
        get => _products[index];
        set => _products[index] = value;
    }
    
    public Product this[string name]
    {
        get => _products.FirstOrDefault(p => p.Name == name);
    }
}

var cart = new ShoppingCart();
cart[0] = new Product();
var product = cart[0];

14. STRUCTS & ENUMS

// Struct (value type, lightweight)
public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
    
    public double DistanceTo(Point other)
    {
        return Math.Sqrt(Math.Pow(X - other.X, 2) + Math.Pow(Y - other.Y, 2));
    }
}

// Using struct
Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
double distance = p1.DistanceTo(p2);

// Record struct (C# 10+)
public record struct Color(int R, int G, int B);

// Enum
public enum DaysOfWeek
{
    Monday,     // 0
    Tuesday,    // 1
    Wednesday,  // 2
    Thursday,   // 3
    Friday,     // 4
    Saturday,   // 5
    Sunday      // 6
}

public enum HttpStatus
{
    OK = 200,
    BadRequest = 400,
    Unauthorized = 401,
    NotFound = 404
}

// Using enums
DaysOfWeek today = DaysOfWeek.Wednesday;
int dayValue = (int)today;              // 2
string dayName = today.ToString();      // "Wednesday"
DaysOfWeek parsed = Enum.Parse<DaysOfWeek>("Monday");
bool isValid = Enum.IsDefined(typeof(DaysOfWeek), 5);  // true

// Flags enum
[Flags]
public enum Permissions
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4,
    All = Read | Write | Execute
}

Permissions perms = Permissions.Read | Permissions.Write;
bool canRead = perms.HasFlag(Permissions.Read);  // true

15. EXCEPTION HANDLING

// Try-catch-finally
try
{
    int result = 10 / int.Parse("0");
}
catch (DivideByZeroException ex)
{
    Console.WriteLine($"Cannot divide by zero: {ex.Message}");
}
catch (FormatException ex) when (ex.Message.Contains("invalid"))
{
    Console.WriteLine("Format exception with filter");
}
catch (Exception ex)  // Generic catch (last)
{
    Console.WriteLine($"Unexpected error: {ex.Message}");
    throw;  // Re-throw exception preserving stack trace
}
finally
{
    Console.WriteLine("Always executes (cleanup)");
}

// Throwing exceptions
public void ValidateAge(int age)
{
    if (age < 0)
        throw new ArgumentException("Age cannot be negative", nameof(age));
    
    if (age > 150)
        throw new ArgumentOutOfRangeException(nameof(age), "Age too high");
    
    if (age < 18)
        throw new InvalidOperationException("User must be 18 or older");
}

// Custom exception
public class InvalidUserException : Exception
{
    public string Username { get; }
    
    public InvalidUserException(string username) 
        : base($"User '{username}' is invalid")
    {
        Username = username;
    }
    
    public InvalidUserException(string username, Exception inner)
        : base($"User '{username}' is invalid", inner)
    {
        Username = username;
    }
}

// Using statement for disposable objects
using (var file = new System.IO.StreamReader("file.txt"))
{
    string content = file.ReadToEnd();
}  // Automatically calls Dispose()

// Using declaration (C# 8+)
using var file2 = new System.IO.StreamReader("file.txt");
string content2 = file2.ReadToEnd();
// Disposed at end of scope

16. DELEGATES & EVENTS

// Delegate declaration
public delegate int MathOperation(int a, int b);

// Using delegate
public class Calculator
{
    public int Add(int a, int b) => a + b;
    public static int Multiply(int a, int b) => a * b;
    
    public void Execute()
    {
        MathOperation op = Add;           // Instance method
        op += Multiply;                    // Multicast
        op += (a, b) => a - b;            // Lambda
        
        int result = op(5, 3);             // All methods execute
        // Last method's result is returned
    }
}

// Func, Action, Predicate delegates
Func<int, int, int> add = (a, b) => a + b;
Action<string> print = (msg) => Console.WriteLine(msg);
Predicate<int> isEven = (x) => x % 2 == 0;

// Events
public class Button
{
    // Event declaration
    public event EventHandler Clicked;
    public event EventHandler<CustomEventArgs> CustomEvent;
    
    protected virtual void OnClicked()
    {
        Clicked?.Invoke(this, EventArgs.Empty);  // Null-conditional invoke
    }
    
    public void SimulateClick()
    {
        OnClicked();
    }
}

// Custom event args
public class CustomEventArgs : EventArgs
{
    public string Message { get; set; }
    public CustomEventArgs(string msg) => Message = msg;
}

// Subscribing to events
Button btn = new Button();
btn.Clicked += (sender, e) => Console.WriteLine("Button clicked");
btn.Clicked += Button_ClickHandler;  // Named method

void Button_ClickHandler(object sender, EventArgs e)
{
    Console.WriteLine("Handler called");
}

// Unsubscribing
btn.Clicked -= Button_ClickHandler;

17. LINQ

using System.Linq;

// Data source
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var people = new List<Person>
{
    new Person { Name = "Alice", Age = 30 },
    new Person { Name = "Bob", Age = 25 },
    new Person { Name = "Charlie", Age = 35 }
};

// Query syntax
var evenNumbers = from n in numbers
                  where n % 2 == 0
                  orderby n descending
                  select n;

var adultNames = from p in people
                 where p.Age >= 18
                 orderby p.Name
                 select p.Name;

// Method syntax (fluent)
var evenNumbers2 = numbers.Where(n => n % 2 == 0)
                          .OrderByDescending(n => n)
                          .Select(n => n);

// Common LINQ methods
var filtered = people.Where(p => p.Age > 25);
var projected = people.Select(p => new { p.Name, p.Age });
var ordered = people.OrderBy(p => p.Age).ThenBy(p => p.Name);
var orderedDesc = people.OrderByDescending(p => p.Age);
var firstMatch = people.First(p => p.Age > 30);
var firstOrDefault = people.FirstOrDefault(p => p.Age > 100);
var single = people.Single(p => p.Age == 25);  // Throws if not exactly one
var any = people.Any(p => p.Age > 40);
var all = people.All(p => p.Age >= 0);
var contains = numbers.Contains(5);
var count = people.Count(p => p.Age > 20);
var sum = numbers.Sum();
var min = numbers.Min();
var max = numbers.Max();
var average = numbers.Average();
var grouped = people.GroupBy(p => p.Age / 10);
var distinct = numbers.Distinct();
var union = numbers.Union(new[] { 11, 12 });
var intersect = numbers.Intersect(new[] { 5, 6, 7, 11 });
var except = numbers.Except(new[] { 1, 2, 3 });
var skip = numbers.Skip(5);
var take = numbers.Take(5);
var skipTake = numbers.Skip(2).Take(3);
var zip = numbers.Zip(new[] { "A", "B", "C" }, (n, s) => $"{n}:{s}");

// Aggregations
var aggregate = numbers.Aggregate((acc, n) => acc + n);
var join = people.Join(numbers, p => p.Age, n => n, 
                       (p, n) => new { p.Name, Number = n });

// Deferred vs immediate execution
var deferred = numbers.Where(n => n > 5);  // Not executed yet
var immediate = numbers.Where(n => n > 5).ToList();  // Executed now

// To collections
List<int> numList = numbers.ToList();
int[] numArray = numbers.ToArray();
Dictionary<int, string> dict = people.ToDictionary(p => p.Age, p => p.Name);
var lookup = people.ToLookup(p => p.Age / 10);

18. FILE I/O

using System.IO;
using System.Text;

// Read all text
string content = File.ReadAllText("file.txt");
string[] lines = File.ReadAllLines("file.txt");

// Write all text
File.WriteAllText("output.txt", "Hello World");
File.WriteAllLines("output.txt", new[] { "Line 1", "Line 2" });
File.AppendAllText("log.txt", "New entry\n");

// Using StreamReader
using (StreamReader reader = new StreamReader("file.txt"))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

// Using StreamWriter
using (StreamWriter writer = new StreamWriter("output.txt"))
{
    writer.WriteLine("Hello");
    writer.Write("World");
}

// Binary files
using (BinaryWriter writer = new BinaryWriter(File.Open("data.bin", FileMode.Create)))
{
    writer.Write(123);
    writer.Write(3.14);
    writer.Write("Text");
}

using (BinaryReader reader = new BinaryReader(File.Open("data.bin", FileMode.Open)))
{
    int num = reader.ReadInt32();
    double dbl = reader.ReadDouble();
    string text = reader.ReadString();
}

// File info
FileInfo fileInfo = new FileInfo("file.txt");
bool exists = fileInfo.Exists;
long size = fileInfo.Length;
DateTime modified = fileInfo.LastWriteTime;
fileInfo.CopyTo("backup.txt");
fileInfo.MoveTo("newfolder/file.txt");
fileInfo.Delete();

// Directory operations
Directory.CreateDirectory("MyFolder");
string[] files = Directory.GetFiles("C:\\MyFolder");
string[] subdirs = Directory.GetDirectories("C:\\MyFolder");
string[] allFiles = Directory.GetFiles("C:\\MyFolder", "*.txt", SearchOption.AllDirectories);
Directory.Delete("MyFolder", recursive: true);

// Path helpers
string combined = Path.Combine("folder", "subfolder", "file.txt");
string fileName = Path.GetFileName("C:\\folder\\file.txt");  // "file.txt"
string extension = Path.GetExtension("file.txt");  // ".txt"
string nameWithoutExt = Path.GetFileNameWithoutExtension("file.txt");  // "file"
string fullPath = Path.GetFullPath("file.txt");
string tempFile = Path.GetTempFileName();
string tempPath = Path.GetTempPath();

19. ASYNCHRONOUS PROGRAMMING

using System.Threading.Tasks;

// Async method signature
public async Task<string> DownloadDataAsync(string url)
{
    using (HttpClient client = new HttpClient())
    {
        string result = await client.GetStringAsync(url);
        return result;
    }
}

// Calling async method
public async Task ProcessDataAsync()
{
    string data = await DownloadDataAsync("https://example.com");
    Console.WriteLine(data);
}

// Async void (only for event handlers)
public async void Button_Click(object sender, EventArgs e)
{
    await Task.Delay(1000);
    Console.WriteLine("After delay");
}

// Parallel execution
public async Task ProcessMultipleAsync()
{
    Task<string> task1 = DownloadDataAsync("https://api1.com");
    Task<string> task2 = DownloadDataAsync("https://api2.com");
    
    // Wait for all
    await Task.WhenAll(task1, task2);
    string result1 = task1.Result;
    string result2 = task2.Result;
    
    // Wait for any
    Task<string> completed = await Task.WhenAny(task1, task2);
    string firstResult = await completed;
}

// Task.Run for CPU-bound work
public async Task<int> CalculateAsync()
{
    return await Task.Run(() =>
    {
        // CPU-intensive work
        int sum = 0;
        for (int i = 0; i < 1000000; i++) sum += i;
        return sum;
    });
}

// Cancellation
public async Task<string> DownloadWithCancellationAsync(string url, CancellationToken token)
{
    using (HttpClient client = new HttpClient())
    {
        var response = await client.GetAsync(url, token);
        return await response.Content.ReadAsStringAsync();
    }
}

// Using cancellation
var cts = new CancellationTokenSource();
cts.CancelAfter(5000);  // Cancel after 5 seconds
try
{
    string result = await DownloadWithCancellationAsync("https://example.com", cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation cancelled");
}

// Progress reporting
public async Task ProcessWithProgressAsync(IProgress<int> progress)
{
    for (int i = 0; i <= 100; i++)
    {
        await Task.Delay(50);
        progress?.Report(i);
    }
}

var progress = new Progress<int>(p => Console.WriteLine($"{p}% complete"));
await ProcessWithProgressAsync(progress);

// ConfigureAwait (avoid deadlocks in UI apps)
string data = await DownloadDataAsync(url).ConfigureAwait(false);

// ValueTask (for performance)
public async ValueTask<int> GetCachedValueAsync()
{
    if (cachedValue.HasValue)
        return cachedValue.Value;
    
    cachedValue = await FetchValueAsync();
    return cachedValue.Value;
}

20. ATTRIBUTES & REFLECTION

// Custom attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class AuthorAttribute : Attribute
{
    public string Name { get; }
    public string Version { get; set; }
    
    public AuthorAttribute(string name)
    {
        Name = name;
    }
}

// Using attributes
[Author("John Doe", Version = "1.0")]
[Author("Jane Smith")]
public class SampleClass
{
    [Author("John Doe")]
    public void MyMethod() { }
}

// Predefined attributes
[Obsolete("Use NewMethod instead")]
public void OldMethod() { }

[Serializable]
public class MyData { }

[Conditional("DEBUG")]
public void DebugOnlyMethod() { }

// Reflection
using System.Reflection;

Type type = typeof(string);
Type personType = new Person().GetType();
Type loadedType = Type.GetType("System.String");

// Get members
MemberInfo[] members = type.GetMembers();
MethodInfo[] methods = type.GetMethods();
PropertyInfo[] properties = type.GetProperties();
FieldInfo[] fields = type.GetFields();
ConstructorInfo[] constructors = type.GetConstructors();

// Invoke methods
MethodInfo method = typeof(Math).GetMethod("Pow");
object result = method.Invoke(null, new object[] { 2.0, 3.0 });  // 8.0

// Create instance
Type listType = typeof(List<int>);
object list = Activator.CreateInstance(listType);
MethodInfo addMethod = listType.GetMethod("Add");
addMethod.Invoke(list, new object[] { 42 });

// Get attributes
var attributes = typeof(SampleClass).GetCustomAttributes(typeof(AuthorAttribute), false);
foreach (AuthorAttribute attr in attributes)
{
    Console.WriteLine($"Author: {attr.Name}");
}

// Dynamic invocation with reflection
public object CallMethod(string className, string methodName, object[] parameters)
{
    Type type = Type.GetType(className);
    object instance = Activator.CreateInstance(type);
    MethodInfo method = type.GetMethod(methodName);
    return method.Invoke(instance, parameters);
}

21. NULLABLE TYPES & NULL SAFETY

// Nullable value types
int? nullableInt = null;
bool? nullableBool = null;
DateTime? nullableDate = null;

// Check if has value
if (nullableInt.HasValue)
{
    int value = nullableInt.Value;  // Throws if null
}

// Safe access
int safeValue = nullableInt ?? 0;  // Default if null
int anotherSafe = nullableInt.GetValueOrDefault(-1);

// Nullable reference types (C# 8+)
#nullable enable
string? nullableString = null;      // Can be null
string nonNullableString = "Hello"; // Cannot be null

// Null-forgiving operator (override warnings)
string forced = nullableString!;    // Suppress warning

// Null-conditional operators
int? length = nullableString?.Length;
Person? person = GetPerson();
string name = person?.Name ?? "Unknown";

// Null coalescing assignment (C# 8+)
person ??= new Person("Default", 0);

// Pattern matching with null
if (person is not null)
{
    Console.WriteLine(person.Name);
}

// Generic nullability
public T? GetDefault<T>() where T : struct  // T? means Nullable<T>
{
    return null;
}

public T? GetDefaultRef<T>() where T : class  // T? can be null
{
    return null;
}
#nullable restore

// Annotation contexts
#nullable disable  // Turn off nullable checks
#nullable enable   // Turn on nullable checks
#nullable restore  // Restore to project default

// Required member (C# 11)
public class Product
{
    public required string Name { get; set; }
    public decimal Price { get; set; } = 0;
}
// var p = new Product();  // Error: Name required

22. RECORDS (C# 9+)

// Basic record (reference type)
public record Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

// Positional record (auto-generated properties)
public record Point(int X, int Y);

// Using records
var p1 = new Person { FirstName = "John", LastName = "Doe" };
var p2 = new Point(10, 20);

// With-expression (non-destructive mutation)
var p3 = p1 with { FirstName = "Jane" };
var p4 = p2 with { X = 30 };

// Value-based equality
var person1 = new Person { FirstName = "Alice", LastName = "Smith" };
var person2 = new Person { FirstName = "Alice", LastName = "Smith" };
bool areEqual = person1 == person2;  // true (by value, not reference)

// Record struct (C# 10+)
public record struct Color(int R, int G, int B);

// Record with methods
public record Product
{
    public string Name { get; init; }
    public decimal Price { get; init; }
    
    public decimal CalculateTax(decimal taxRate) => Price * taxRate;
    
    // Custom equality
    public virtual bool Equals(Product other)
    {
        return Name == other.Name;
    }
}

// Inheritance with records
public record Animal(string Name);
public record Dog(string Name, string Breed) : Animal(Name);

// JSON serialization friendly
var record = new Person { FirstName = "John", LastName = "Doe" };
string json = System.Text.Json.JsonSerializer.Serialize(record);
var deserialized = System.Text.Json.JsonSerializer.Deserialize<Person>(json);

23. PATTERN MATCHING (C# 7-11)

// Type pattern
object obj = "Hello";
if (obj is string s)
{
    Console.WriteLine($"String length: {s.Length}");
}

// Switch expression pattern (C# 8+)
string GetTypeName(object obj) => obj switch
{
    int i => $"Integer: {i}",
    string s => $"String: {s}",
    double d => $"Double: {d}",
    null => "Null",
    _ => "Unknown"
};

// Property pattern
if (person is { Age: > 18, Name: string name })
{
    Console.WriteLine($"{name} is adult");
}

// Tuple pattern
string GetQuadrant(Point p) => (p.X, p.Y) switch
{
    (>0, >0) => "Q1",
    (<0, >0) => "Q2",
    (<0, <0) => "Q3",
    (>0, <0) => "Q4",
    (0, _) => "On Y axis",
    (_, 0) => "On X axis",
    _ => "Origin"
};

// Positional pattern
public record Point2D(int X, int Y);
string Describe(Point2D point) => point switch
{
    (0, 0) => "Origin",
    (var x, 0) => $"On X axis at {x}",
    (0, var y) => $"On Y axis at {y}",
    var (x, y) => $"At ({x}, {y})"
};

// Relational pattern (C# 9+)
string GetGrade(int score) => score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    < 60 => "F"
};

// Logical patterns (C# 9+)
bool IsValidAge(int age) => age is >= 0 and <= 150;
bool IsTeenager(int age) => age is >= 13 and <= 19;
bool IsValidChar(char c) => c is not '\0';

// List patterns (C# 11+)
int[] numbers = { 1, 2, 3, 4, 5 };
string DescribeArray(int[] arr) => arr switch
{
    [] => "Empty",
    [var first] => $"Single element: {first}",
    [var first, var second] => $"Two elements: {first}, {second}",
    [var first, .., var last] => $"Starts with {first}, ends with {last}",
    [1, 2, ..] => "Starts with 1,2",
    [.., 5] => "Ends with 5",
    _ => "Other"
};

// Var pattern
if (int.TryParse(input, out var result))
{
    Console.WriteLine($"Parsed: {result}");
}

24. TOP-LEVEL STATEMENTS (C# 9+)

// Entire program without namespace, class, Main
using System;
using System.Linq;

Console.WriteLine("Hello World!");

// Variables
string name = "John";
int age = 30;

// Methods can be defined
void Greet(string person)
{
    Console.WriteLine($"Hello, {person}");
}

Greet(name);

// Can return exit code
// return 0;

// Can use async
// await Task.Delay(1000);

// Can access command line args
if (args.Length > 0)
{
    Console.WriteLine($"Args: {string.Join(", ", args)}");
}

// Traditional Main equivalent
// args variable is available
foreach (var arg in args)
{
    Console.WriteLine(arg);
}

📌 QUICK REFERENCE CARD

Category Syntax Example
Write to console Console.WriteLine("text")
Read from console string input = Console.ReadLine()
Parse string to int int.Parse("123") or int.TryParse("123", out int result)
String interpolation $"Value: {x}"
List creation new List<int> { 1, 2, 3 }
Dictionary new Dictionary<string, int>()
Exception try { } catch (Exception ex) { } finally { }
Async method async Task<T> MethodName()
Wait for task await task
LINQ query from x in collection where x > 5 select x
Lambda (x, y) => x + y
Null check if (obj is null)
Pattern matching obj is string s
Property with validation public int Prop { get => _prop; set => _prop = value > 0 ? value : 0; }
Constructor public ClassName(parameters) : base(param) { }

🔧 COMMON NAMING CONVENTIONS

Element Convention Example
Namespaces PascalCase System.Collections
Classes PascalCase CustomerService
Interfaces I + PascalCase IRepository
Methods PascalCase CalculateTotal()
Properties PascalCase FirstName
Fields (private) _camelCase _customerId
Parameters camelCase firstName
Local variables camelCase itemCount
Constants PascalCase MaxRetryCount