C# Mastery Guide
Complete guide from beginner to advanced
The Complete C# Mastery Guide
A comprehensive journey through C# fundamentals to advanced .NET development concepts.
Understanding C#: The Modern .NET Language
C# (pronounced "C Sharp") is a modern, object-oriented, and type-safe programming language developed by Microsoft. Created by Anders Hejlsberg and his team in 2000, C# has evolved into one of the most popular languages for building enterprise applications, games, web services, and mobile apps.
C# runs on the .NET framework and .NET Core, providing a robust ecosystem for building cross-platform applications. It combines the power of C++ with the simplicity of Visual Basic and brings modern features like LINQ, async/await, and pattern matching to developers.
Did you know? C# was originally named "Cool" (C-like Object Oriented Language) but was renamed to C# for trademark reasons. The '#' symbol represents four plus signs, indicating it's a step beyond C++.
1. C# Basics & Syntax
Hello World and Basic Structure
using System; namespace HelloWorld { class Program { static void Main(string[] args) { // Basic output Console.WriteLine("Hello, World!"); // Input from user Console.Write("Enter your name: "); string name = Console.ReadLine(); Console.WriteLine($"Hello, {name}!"); // Command line arguments if (args.Length > 0) { Console.WriteLine($"First argument: {args[0]}"); } } } } // Modern C# 9.0+ Top-level statements (no namespace/class required) using System; Console.WriteLine("Hello, World!"); Console.Write("Enter your name: "); string name = Console.ReadLine(); Console.WriteLine($"Hello, {name}!");
Variables and Data Types
using System; class DataTypes { static void Main() { // Value types int age = 25; // 32-bit integer long bigNumber = 123456789L; // 64-bit integer double price = 19.99; // Double-precision floating point decimal salary = 50000.50M; // Decimal for financial calculations float temperature = 23.5f; // Single-precision floating point char grade = 'A'; // Single character bool isActive = true; // Boolean // Reference types string name = "John Doe"; // String object obj = new object(); // Base object type dynamic dynamicVar = "Hello"; // Dynamic type (resolved at runtime) // Nullable value types int? nullableInt = null; // Can hold null nullableInt = 42; // Now has value // Type inference with var var count = 10; // Compiler infers int var message = "Hello"; // Compiler infers string var numbers = new int[] {1, 2, 3}; // Compiler infers int[] // Constants const double PI = 3.14159; const string APP_NAME = "My Application"; // Displaying values Console.WriteLine($"Name: {name}, Age: {age}"); Console.WriteLine($"Price: {price:C}"); // Currency format Console.WriteLine($"Temperature: {temperature:F1}°C"); // 1 decimal place // Type information Console.WriteLine($"Type of count: {count.GetType()}"); Console.WriteLine($"Type of message: {message.GetType()}"); } }
Operators and Expressions
using System; class Operators { static void Main() { // Arithmetic operators int a = 10, b = 3; int sum = a + b; // 13 int difference = a - b; // 7 int product = a * b; // 30 int quotient = a / b; // 3 (integer division) double realQuotient = (double)a / b; // 3.333... int remainder = a % b; // 1 int increment = a++; // Post-increment: 10 (a becomes 11) int decrement = --b; // Pre-decrement: 2 (b becomes 2) // Assignment operators int x = 10; x += 5; // x = x + 5 → 15 x -= 3; // x = x - 3 → 12 x *= 2; // x = x * 2 → 24 x /= 4; // x = x / 4 → 6 x %= 5; // x = x % 5 → 1 // Comparison operators bool isEqual = (a == b); // false bool notEqual = (a != b); // true bool greaterThan = (a > b); // true bool lessOrEqual = (a <= b); // false // Logical operators bool condition1 = true, condition2 = false; bool andResult = condition1 && condition2; // false bool orResult = condition1 || condition2; // true bool notResult = !condition1; // false // Ternary operator int number = 15; string result = (number % 2 == 0) ? "Even" : "Odd"; Console.WriteLine($"{number} is {result}"); // Null-coalescing operator string nullableString = null; string safeString = nullableString ?? "Default Value"; Console.WriteLine(safeString); // "Default Value" // Null-conditional operator (C# 6.0+) string[] names = null; int? length = names?.Length; // null instead of exception string first = names?[0]; // null instead of exception // Bitwise operators int flags = 5; // Binary: 101 int mask = 3; // Binary: 011 int bitwiseAnd = flags & mask; // 1 (001) int bitwiseOr = flags | mask; // 7 (111) int bitwiseXor = flags ^ mask; // 6 (110) int leftShift = flags << 1; // 10 (1010) int rightShift = flags >> 1; // 2 (010) Console.WriteLine($"Bitwise operations: AND={bitwiseAnd}, OR={bitwiseOr}"); } }
Control Flow Statements
using System; class ControlFlow { static void Main() { // If-else statements int temperature = 22; if (temperature > 30) { Console.WriteLine("It's a hot day!"); Console.WriteLine("Stay hydrated!"); } else if (temperature > 20) { Console.WriteLine("Perfect weather!"); Console.WriteLine("Enjoy outdoors!"); } else { Console.WriteLine("It's cold outside!"); Console.WriteLine("Dress warmly!"); } // Switch statement string day = "Monday"; switch (day) { case "Monday": Console.WriteLine("Start of the work week"); break; case "Friday": Console.WriteLine("Weekend is almost here!"); break; case "Saturday": case "Sunday": Console.WriteLine("Weekend!"); break; default: Console.WriteLine("Regular work day"); break; } // Switch expression (C# 8.0+) string message = day switch { "Monday" => "Start of week", "Friday" => "Almost weekend", "Saturday" or "Sunday" => "Weekend!", _ => "Regular day" }; Console.WriteLine(message); // While loop int count = 1; while (count <= 5) { Console.WriteLine($"While count: {count}"); count++; } // Do-while loop (executes at least once) int number = 1; do { Console.WriteLine($"Do-while number: {number}"); number++; } while (number <= 3); // For loop for (int i = 0; i < 5; i++) { Console.WriteLine($"For iteration: {i}"); } // Foreach loop string[] fruits = { "apple", "banana", "orange" }; foreach (string fruit in fruits) { Console.WriteLine($"Fruit: {fruit}"); } // Loop control statements for (int i = 0; i < 10; i++) { if (i == 3) continue; // Skip this iteration if (i == 7) break; // Exit loop Console.WriteLine($"Number: {i}"); } // Exception handling with try-catch try { Console.Write("Enter a number: "); string input = Console.ReadLine(); int parsedNumber = int.Parse(input); Console.WriteLine($"You entered: {parsedNumber}"); } catch (FormatException) { Console.WriteLine("Invalid number format!"); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } finally { Console.WriteLine("This always executes"); } } }
2. Object-Oriented Programming
Classes and Objects
using System; namespace OOPBasics { // Basic class definition public class Person { // Fields (private by convention) private string name; private int age; // Properties (public interface) public string Name { get { return name; } set { if (!string.IsNullOrWhiteSpace(value)) name = value; } } public int Age { get { return age; } set { if (value >= 0 && value <= 150) age = value; } } // Auto-implemented property public string Email { get; set; } // Read-only property public string DisplayName => $"{Name} ({Age})"; // Constructors public Person() { } public Person(string name, int age) { Name = name; Age = age; } // Methods public void Introduce() { Console.WriteLine($"Hello, my name is {Name} and I am {Age} years old."); } public string GetBirthYear() { int currentYear = DateTime.Now.Year; return $"Born around {currentYear - Age}"; } // Static method public static void DisplaySpecies() { Console.WriteLine("Species: Homo sapiens"); } } class Program { static void Main() { // Creating objects Person person1 = new Person(); person1.Name = "John Doe"; person1.Age = 25; person1.Email = "john@example.com"; Person person2 = new Person("Jane Smith", 30); // Using methods person1.Introduce(); person2.Introduce(); // Using properties Console.WriteLine($"{person1.Name}'s display: {person1.DisplayName}"); Console.WriteLine(person1.GetBirthYear()); // Static method call Person.DisplaySpecies(); // Object initializer syntax Person person3 = new Person { Name = "Bob Johnson", Age = 35, Email = "bob@example.com" }; person3.Introduce(); } } }
Inheritance and Polymorphism
using System; using System.Collections.Generic; namespace OOPAdvanced { // Base class public abstract class Animal { public string Name { get; set; } public int Age { get; set; } // Virtual method - can be overridden public virtual void MakeSound() { Console.WriteLine("Some generic animal sound"); } // Abstract method - must be implemented by derived classes public abstract void Move(); // Regular method public void Sleep() { Console.WriteLine($"{Name} is sleeping..."); } } // Interface public interface IPet { string Owner { get; set; } void Play(); } // Derived class public class Dog : Animal, IPet { public string Breed { get; set; } public string Owner { get; set; } // Constructor public Dog(string name, string breed) { Name = name; Breed = breed; } // Override virtual method public override void MakeSound() { Console.WriteLine("Woof! Woof!"); } // Implement abstract method public override void Move() { Console.WriteLine($"{Name} is running on four legs"); } // Implement interface method public void Play() { Console.WriteLine($"{Name} is playing fetch with {Owner}"); } // New method specific to Dog public void WagTail() { Console.WriteLine($"{Name} is wagging its tail"); } } // Another derived class public class Cat : Animal, IPet { public bool IsIndoor { get; set; } public string Owner { get; set; } public override void MakeSound() { Console.WriteLine("Meow! Meow!"); } public override void Move() { Console.WriteLine($"{Name} is walking gracefully"); } public void Play() { Console.WriteLine($"{Name} is playing with a ball of yarn"); } public void Purr() { Console.WriteLine($"{Name} is purring..."); } } class Program { static void Main() { // Polymorphism in action List<Animal> animals = new List<Animal> { new Dog("Buddy", "Golden Retriever") { Owner = "John", Age = 3 }, new Cat("Whiskers", true) { Owner = "Jane", Age = 2 } }; foreach (Animal animal in animals) { Console.WriteLine($"\n{animal.Name}:"); animal.MakeSound(); animal.Move(); animal.Sleep(); // Type checking and casting if (animal is IPet pet) { pet.Play(); } if (animal is Dog dog) { dog.WagTail(); } else if (animal is Cat cat) { cat.Purr(); } } // Using interface reference IPet myPet = new Dog("Max", "Labrador") { Owner = "Alice" }; myPet.Play(); } } // Sealed class - cannot be inherited public sealed class FinalClass { public string Message { get; set; } } // This would cause error: // public class DerivedClass : FinalClass { } }
Encapsulation and Access Modifiers
using System; namespace EncapsulationExample { public class BankAccount { // Private fields - only accessible within this class private string accountNumber; private decimal balance; private string accountHolder; private DateTime createdDate; // Public properties with controlled access public string AccountNumber { get { return accountNumber; } private set { accountNumber = value; } } public decimal Balance { get { return balance; } private set { balance = value; } } public string AccountHolder { get { return accountHolder; } set { if (!string.IsNullOrWhiteSpace(value)) accountHolder = value; } } public DateTime CreatedDate { get { return createdDate; } } // Read-only property public bool IsActive => Balance >= 0; // Constructor public BankAccount(string accountHolder, string accountNumber, decimal initialDeposit = 0) { if (initialDeposit < 0) throw new ArgumentException("Initial deposit cannot be negative"); AccountHolder = accountHolder; this.accountNumber = accountNumber; this.balance = initialDeposit; this.createdDate = DateTime.Now; } // Public methods to manipulate balance public void Deposit(decimal amount) { if (amount <= 0) throw new ArgumentException("Deposit amount must be positive"); balance += amount; LogTransaction($"Deposited: {amount:C}"); } public bool Withdraw(decimal amount) { if (amount <= 0) throw new ArgumentException("Withdrawal amount must be positive"); if (balance >= amount) { balance -= amount; LogTransaction($"Withdrew: {amount:C}"); return true; } Console.WriteLine("Insufficient funds!"); return false; } public void Transfer(BankAccount targetAccount, decimal amount) { if (targetAccount == null) throw new ArgumentNullException(nameof(targetAccount)); if (Withdraw(amount)) { targetAccount.Deposit(amount); LogTransaction($"Transferred: {amount:C} to {targetAccount.AccountNumber}"); } } // Private helper method - only accessible within this class private void LogTransaction(string message) { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}"); Console.WriteLine($"[Balance: {Balance:C}]"); } // Protected method - accessible within this class and derived classes protected virtual void OnAccountAction(string action) { Console.WriteLine($"Account action: {action}"); } // Internal method - accessible within the same assembly internal void InternalMethod() { Console.WriteLine("Internal method called"); } } // Derived class with additional functionality public class SavingsAccount : BankAccount { private decimal interestRate; public decimal InterestRate { get { return interestRate; } set { if (value >= 0 && value <= 1) interestRate = value; } } public SavingsAccount(string accountHolder, string accountNumber, decimal interestRate) : base(accountHolder, accountNumber) { InterestRate = interestRate; } public void ApplyInterest() { decimal interest = Balance * InterestRate; Deposit(interest); OnAccountAction($"Interest applied: {interest:C}"); } // Override protected method protected override void OnAccountAction(string action) { base.OnAccountAction(action); Console.WriteLine($"Savings Account - {action}"); } } class Program { static void Main() { // Create accounts BankAccount checking = new BankAccount("John Doe", "CHK12345", 1000); SavingsAccount savings = new SavingsAccount("John Doe", "SAV67890", 0.02m); // Test operations checking.Deposit(500); checking.Withdraw(200); checking.Transfer(savings, 300); savings.ApplyInterest(); // Display account information Console.WriteLine($"\nChecking Account: {checking.Balance:C}"); Console.WriteLine($"Savings Account: {savings.Balance:C}"); Console.WriteLine($"Checking Active: {checking.IsActive}"); Console.WriteLine($"Account Created: {checking.CreatedDate:yyyy-MM-dd}"); // This would cause errors (private setters): // checking.Balance = 1000000; // Error! // checking.AccountNumber = "NEW123"; // Error! } } }
3. Data Structures & Collections
Arrays and Strings
using System; namespace ArraysAndStrings { class Program { static void Main() { // Single-dimensional arrays int[] numbers = new int[5]; numbers[0] = 1; numbers[1] = 2; numbers[2] = 3; numbers[3] = 4; numbers[4] = 5; // Array initialization int[] primes = { 2, 3, 5, 7, 11 }; string[] fruits = { "apple", "banana", "orange" }; // Multi-dimensional arrays int[,] matrix = new int[3, 3] { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // Jagged arrays (array of arrays) int[][] jagged = new int[3][]; jagged[0] = new int[] {1, 2, 3}; jagged[1] = new int[] {4, 5}; jagged[2] = new int[] {6, 7, 8, 9}; // Array methods and properties Console.WriteLine($"Array length: {numbers.Length}"); Console.WriteLine($"Array rank: {matrix.Rank}"); Console.WriteLine($"Array dimensions: {matrix.GetLength(0)}x{matrix.GetLength(1)}"); Array.Sort(primes); Array.Reverse(primes); int index = Array.IndexOf(primes, 5); // String basics string firstName = "John"; string lastName = "Doe"; string fullName = firstName + " " + lastName; string interpolated = $"{firstName} {lastName}"; string formatted = string.Format("{0} {1}", firstName, lastName); // String methods string text = " Hello, World! "; Console.WriteLine($"Original: '{text}'"); Console.WriteLine($"Trimmed: '{text.Trim()}'"); Console.WriteLine($"Upper: {text.ToUpper()}"); Console.WriteLine($"Lower: {text.ToLower()}"); Console.WriteLine($"Length: {text.Length}"); Console.WriteLine($"Contains 'World': {text.Contains("World")}"); Console.WriteLine($"StartsWith 'Hello': {text.Trim().StartsWith("Hello")}"); Console.WriteLine($"Index of 'World': {text.IndexOf("World")}"); // String splitting and joining string csv = "apple,banana,orange,grape"; string[] fruitArray = csv.Split(','); string joined = string.Join(" - ", fruitArray); Console.WriteLine($"Joined: {joined}"); // String building for efficient concatenation var sb = new System.Text.StringBuilder(); for (int i = 0; i < 10; i++) { sb.Append(i); sb.Append(" "); } string result = sb.ToString(); Console.WriteLine($"StringBuilder result: {result}"); // String comparison string str1 = "hello"; string str2 = "HELLO"; bool equal1 = str1 == str2; // false bool equal2 = str1.Equals(str2); // false bool equal3 = str1.Equals(str2, StringComparison.OrdinalIgnoreCase); // true Console.WriteLine($"\nString comparisons:"); Console.WriteLine($"== : {equal1}"); Console.WriteLine($"Equals: {equal2}"); Console.WriteLine($"Ignore case: {equal3}"); // String formatting DateTime now = DateTime.Now; string dateString = string.Format("Today is {0:yyyy-MM-dd} and time is {0:HH:mm:ss}", now); Console.WriteLine(dateString); decimal price = 19.99m; Console.WriteLine($"Price: {price:C}"); // Currency Console.WriteLine($"Price: {price:F2}"); // Fixed point Console.WriteLine($"Large number: {1234567:N0}"); // Number with commas } } }
Collections and Generics
using System; using System.Collections.Generic; using System.Linq; namespace CollectionsExample { class Program { static void Main() { // List<T> - Dynamic array List<string> fruits = new List<string> { "apple", "banana" }; fruits.Add("orange"); fruits.AddRange(new[] { "grape", "mango" }); fruits.Insert(1, "kiwi"); fruits.Remove("banana"); fruits.RemoveAt(0); Console.WriteLine("List operations:"); foreach (string fruit in fruits) { Console.WriteLine($" - {fruit}"); } Console.WriteLine($"Count: {fruits.Count}"); Console.WriteLine($"Contains 'orange': {fruits.Contains("orange")}"); Console.WriteLine($"Index of 'grape': {fruits.IndexOf("grape")}"); // Dictionary<TKey, TValue> - Key-value pairs Dictionary<string, int> ages = new Dictionary<string, int> { ["John"] = 25, ["Jane"] = 30, ["Bob"] = 35 }; ages["Alice"] = 28; // Add or update ages.TryAdd("Charlie", 40); // Safe add Console.WriteLine("\nDictionary operations:"); foreach (KeyValuePair<string, int> kvp in ages) { Console.WriteLine($" {kvp.Key}: {kvp.Value} years old"); } if (ages.TryGetValue("John", out int johnsAge)) { Console.WriteLine($"John's age: {johnsAge}"); } // HashSet<T> - Unique elements HashSet<int> uniqueNumbers = new HashSet<int> { 1, 2, 3, 4, 5 }; uniqueNumbers.Add(3); // Won't add duplicate uniqueNumbers.Add(6); // Will add new HashSet<int> otherNumbers = new HashSet<int> { 4, 5, 6, 7, 8 }; Console.WriteLine("\nHashSet operations:"); Console.WriteLine($"Union: {string.Join(", ", uniqueNumbers.Union(otherNumbers))}"); Console.WriteLine($"Intersection: {string.Join(", ", uniqueNumbers.Intersect(otherNumbers))}"); Console.WriteLine($"Difference: {string.Join(", ", uniqueNumbers.Except(otherNumbers))}"); // Queue<T> - FIFO (First In First Out) Queue<string> queue = new Queue<string>(); queue.Enqueue("first"); queue.Enqueue("second"); queue.Enqueue("third"); Console.WriteLine("\nQueue operations:"); while (queue.Count > 0) { string item = queue.Dequeue(); Console.WriteLine($"Dequeued: {item}"); } // Stack<T> - LIFO (Last In First Out) Stack<string> stack = new Stack<string>(); stack.Push("first"); stack.Push("second"); stack.Push("third"); Console.WriteLine("\nStack operations:"); while (stack.Count > 0) { string item = stack.Pop(); Console.WriteLine($"Popped: {item}"); } // LinkedList<T> - Doubly linked list LinkedList<string> linkedList = new LinkedList<string>(); linkedList.AddLast("apple"); linkedList.AddLast("banana"); linkedList.AddFirst("orange"); // Becomes first Console.WriteLine("\nLinkedList operations:"); LinkedListNode<string> currentNode = linkedList.First; while (currentNode != null) { Console.WriteLine($"Node: {currentNode.Value}"); currentNode = currentNode.Next; } // Sorted collections SortedList<string, int> sortedAges = new SortedList<string, int> { ["Charlie"] = 40, ["Alice"] = 28, ["Bob"] = 35 }; Console.WriteLine("\nSortedList (automatically sorted by key):"); foreach (var kvp in sortedAges) { Console.WriteLine($" {kvp.Key}: {kvp.Value}"); } // Collection initialization with custom objects List<Person> people = new List<Person> { new Person("John", 25), new Person("Jane", 30), new Person("Bob", 35) }; Console.WriteLine("\nCustom objects in collection:"); foreach (Person person in people) { Console.WriteLine($" {person.Name} - {person.Age} years"); } } } public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } } }
4. Advanced C# Features
Delegates, Events, and Lambdas
using System; namespace AdvancedFeatures { // Delegate declarations public delegate void SimpleDelegate(string message); public delegate int MathOperation(int a, int b); public delegate bool FilterCondition(int number); public class Calculator { // Method that matches MathOperation signature public static int Add(int a, int b) => a + b; public static int Multiply(int a, int b) => a * b; public static int Subtract(int a, int b) => a - b; } // Event publisher class public class Button { // Event declaration public event EventHandler<string> Clicked; public void Click() { Console.WriteLine("Button was clicked!"); OnClicked("Button click event raised"); } protected virtual void OnClicked(string message) { Clicked?.Invoke(this, message); } } public class AdvancedDemo { public static void DemonstrateDelegates() { Console.WriteLine("=== DELEGATES ==="); // Instantiate delegates SimpleDelegate simple = PrintMessage; MathOperation mathOp = Calculator.Add; // Invoke delegates simple("Hello from delegate!"); int result = mathOp(10, 5); Console.WriteLine($"10 + 5 = {result}"); // Multicast delegates SimpleDelegate multi = PrintMessage; multi += PrintUpperCase; multi += (msg) => Console.WriteLine($"Lambda: {msg}"); multi("Multicast demo"); // Change delegate reference mathOp = Calculator.Multiply; result = mathOp(10, 5); Console.WriteLine($"10 * 5 = {result}"); } public static void DemonstrateEvents() { Console.WriteLine("\n=== EVENTS ==="); Button button = new Button(); // Subscribe to event button.Clicked += (sender, message) => { Console.WriteLine($"Event handled: {message}"); }; button.Clicked += Button_Clicked; // Trigger event button.Click(); // Unsubscribe button.Clicked -= Button_Clicked; } private static void Button_Clicked(object sender, string message) { Console.WriteLine($"Additional handler: {message}"); } public static void DemonstrateLambdas() { Console.WriteLine("\n=== LAMBDA EXPRESSIONS ==="); // Lambda expressions MathOperation add = (a, b) => a + b; MathOperation multiply = (a, b) => a * b; Console.WriteLine($"Lambda add: {add(7, 3)}"); Console.WriteLine($"Lambda multiply: {multiply(7, 3)}"); // Using built-in Func and Action delegates Func<int, int, int> funcAdd = (a, b) => a + b; Action<string> actionPrint = (msg) => Console.WriteLine(msg); actionPrint($"Func result: {funcAdd(15, 25)}"); // Complex lambda with multiple statements Func<int, int, string> complex = (a, b) => { int sum = a + b; return $"The sum of {a} and {b} is {sum}"; }; Console.WriteLine(complex(8, 12)); // Using lambda with collections int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // Filter even numbers using lambda var evenNumbers = Array.FindAll(numbers, n => n % 2 == 0); Console.WriteLine("Even numbers: " + string.Join(", ", evenNumbers)); // Transform numbers using lambda var squared = Array.ConvertAll(numbers, n => n * n); Console.WriteLine("Squared numbers: " + string.Join(", ", squared)); } public static void DemonstrateAnonymousMethods() { Console.WriteLine("\n=== ANONYMOUS METHODS ==="); // Anonymous method (older syntax) MathOperation oldStyle = delegate(int a, int b) { return a + b; }; Console.WriteLine($"Anonymous method: {oldStyle(20, 30)}"); } // Method that matches SimpleDelegate signature public static void PrintMessage(string message) { Console.WriteLine($"Message: {message}"); } public static void PrintUpperCase(string message) { Console.WriteLine($"UPPER: {message.ToUpper()}"); } } class Program { static void Main() { AdvancedDemo.DemonstrateDelegates(); AdvancedDemo.DemonstrateEvents(); AdvancedDemo.DemonstrateLambdas(); AdvancedDemo.DemonstrateAnonymousMethods(); } } }
Extension Methods and Partial Classes
using System; using System.Collections.Generic; using System.Text; namespace ExtensionMethodsDemo { // Extension methods must be in static class public static class StringExtensions { // Extension method for string class public static string Reverse(this string str) { if (string.IsNullOrEmpty(str)) return str; char[] charArray = str.ToCharArray(); Array.Reverse(charArray); return new string(charArray); } public static bool IsPalindrome(this string str) { if (string.IsNullOrEmpty(str)) return false; string clean = str.ToLower().Replace(" ", ""); return clean == clean.Reverse(); } public static string ToTitleCase(this string str) { if (string.IsNullOrEmpty(str)) return str; string[] words = str.Split(' '); for (int i = 0; i < words.Length; i++) { if (!string.IsNullOrEmpty(words[i])) { words[i] = char.ToUpper(words[i][0]) + words[i].Substring(1).ToLower(); } } return string.Join(" ", words); } } public static class CollectionExtensions { public static void PrintAll<T>(this IEnumerable<T> collection) { Console.WriteLine($"[{string.Join(", ", collection)}]"); } public static string ToDelimitedString<T>(this IEnumerable<T> collection, string delimiter = ", ") { return string.Join(delimiter, collection); } public static bool IsEmpty<T>(this ICollection<T> collection) { return collection.Count == 0; } } public static class NumberExtensions { public static bool IsEven(this int number) => number % 2 == 0; public static bool IsOdd(this int number) => number % 2 != 0; public static bool IsPrime(this int number) { if (number <= 1) return false; if (number == 2) return true; if (number % 2 == 0) return false; for (int i = 3; i * i <= number; i += 2) { if (number % i == 0) return false; } return true; } public static int Squared(this int number) => number * number; public static double ToRadians(this double degrees) => degrees * Math.PI / 180; public static double ToDegrees(this double radians) => radians * 180 / Math.PI; } // Partial class example - split across multiple files public partial class Employee { public string FirstName { get; set; } public string LastName { get; set; } public decimal Salary { get; set; } public Employee(string firstName, string lastName, decimal salary) { FirstName = firstName; LastName = lastName; Salary = salary; } // Partial method declaration (must be void) partial void OnSalaryChanged(decimal oldSalary, decimal newSalary); public void RaiseSalary(decimal amount) { decimal oldSalary = Salary; Salary += amount; OnSalaryChanged(oldSalary, Salary); // Call partial method } } // Second part of partial class (could be in separate file) public partial class Employee { public string FullName => $"{FirstName} {LastName}"; public string GetInfo() { return $"{FullName} - Salary: {Salary:C}"; } // Implementation of partial method partial void OnSalaryChanged(decimal oldSalary, decimal newSalary) { Console.WriteLine($"Salary changed from {oldSalary:C} to {newSalary:C}"); } // Additional methods public void DisplayEmployee() { Console.WriteLine(GetInfo()); } } class Program { static void Main() { Console.WriteLine("=== EXTENSION METHODS ==="); // Using string extensions string text = "Hello World"; Console.WriteLine($"Original: {text}"); Console.WriteLine($"Reversed: {text.Reverse()}"); Console.WriteLine($"Title Case: {text.ToTitleCase()}"); Console.WriteLine($"Is Palindrome 'radar': {"radar".IsPalindrome()}"); Console.WriteLine($"Is Palindrome 'hello': {"hello".IsPalindrome()}"); // Using collection extensions List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; Console.WriteLine("\nCollection extensions:"); numbers.PrintAll(); Console.WriteLine($"Delimited: {numbers.ToDelimitedString(" | ")}"); Console.WriteLine($"Is empty: {numbers.IsEmpty()}"); // Using number extensions int testNumber = 17; Console.WriteLine("\nNumber extensions:"); Console.WriteLine($"{testNumber} is even: {testNumber.IsEven()}"); Console.WriteLine($"{testNumber} is odd: {testNumber.IsOdd()}"); Console.WriteLine($"{testNumber} is prime: {testNumber.IsPrime()}"); Console.WriteLine($"{testNumber} squared: {testNumber.Squared()}"); // Using partial class Console.WriteLine("\n=== PARTIAL CLASS ==="); Employee emp = new Employee("John", "Doe", 50000); emp.DisplayEmployee(); emp.RaiseSalary(10000); emp.DisplayEmployee(); // Real-world example: Building a query with extensions Console.WriteLine("\n=== PRACTICAL EXAMPLE ==="); var primes = new List<int>(); for (int i = 1; i <= 20; i++) { if (i.IsPrime()) primes.Add(i); } Console.WriteLine($"Primes 1-20: {primes.ToDelimitedString()}"); } } }
5. LINQ & Functional Programming
LINQ Fundamentals
using System; using System.Collections.Generic; using System.Linq; namespace LINQFundamentals { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } public int Stock { get; set; } public override string ToString() => $"{Name} ({Category}) - {Price:C}"; } class Program { static void Main() { // Sample data List<Product> products = new List<Product> { new Product { Id = 1, Name = "Laptop", Category = "Electronics", Price = 999.99m, Stock = 10 }, new Product { Id = 2, Name = "Mouse", Category = "Electronics", Price = 25.50m, Stock = 50 }, new Product { Id = 3, Name = "Desk", Category = "Furniture", Price = 299.99m, Stock = 5 }, new Product { Id = 4, Name = "Chair", Category = "Furniture", Price = 149.99m, Stock = 15 }, new Product { Id = 5, Name = "Monitor", Category = "Electronics", Price = 199.99m, Stock = 8 }, new Product { Id = 6, Name = "Keyboard", Category = "Electronics", Price = 75.00m, Stock = 25 }, new Product { Id = 7, Name = "Bookshelf", Category = "Furniture", Price = 179.99m, Stock = 3 }, new Product { Id = 8, Name = "Tablet", Category = "Electronics", Price = 349.99m, Stock = 12 } }; // LINQ Query Syntax Console.WriteLine("=== QUERY SYNTAX ==="); // Basic filtering var expensiveProducts = from p in products where p.Price > 100 select p; Console.WriteLine("Products over $100:"); foreach (var product in expensiveProducts) { Console.WriteLine($" - {product}"); } // Filtering and ordering var electronicsByPrice = from p in products where p.Category == "Electronics" orderby p.Price descending select p; Console.WriteLine("\nElectronics by price (descending):"); foreach (var product in electronicsByPrice) { Console.WriteLine($" - {product}"); } // Grouping var productsByCategory = from p in products group p by p.Category into categoryGroup select new { Category = categoryGroup.Key, Count = categoryGroup.Count(), TotalValue = categoryGroup.Sum(p => p.Price * p.Stock) }; Console.WriteLine("\nProducts by category:"); foreach (var group in productsByCategory) { Console.WriteLine($" {group.Category}: {group.Count} products, Total value: {group.TotalValue:C}"); } // Joining (if we had another collection) var categories = new List<string> { "Electronics", "Furniture", "Clothing" }; var categoryProducts = from c in categories join p in products on c equals p.Category into productGroup select new { Category = c, Products = productGroup }; Console.WriteLine("\nProducts by category (with join):"); foreach (var item in categoryProducts) { Console.WriteLine($"\n{item.Category}:"); foreach (var product in item.Products) { Console.WriteLine($" - {product.Name}"); } } // LINQ Method Syntax Console.WriteLine("\n=== METHOD SYNTAX ==="); // Basic filtering var cheapProducts = products.Where(p => p.Price < 100); Console.WriteLine("Products under $100:"); cheapProducts.ToList().ForEach(p => Console.WriteLine($" - {p}")); // Complex queries var lowStockElectronics = products .Where(p => p.Category == "Electronics" && p.Stock < 15) .OrderBy(p => p.Stock) .Select(p => new { p.Name, p.Stock, p.Price }); Console.WriteLine("\nLow stock electronics:"); foreach (var item in lowStockElectronics) { Console.WriteLine($" - {item.Name}: {item.Stock} in stock, {item.Price:C}"); } // Aggregation methods Console.WriteLine("\n=== AGGREGATION ==="); decimal totalValue = products.Sum(p => p.Price * p.Stock); decimal averagePrice = products.Average(p => p.Price); decimal maxPrice = products.Max(p => p.Price); decimal minPrice = products.Min(p => p.Price); int totalProducts = products.Count(); Console.WriteLine($"Total inventory value: {totalValue:C}"); Console.WriteLine($"Average price: {averagePrice:C}"); Console.WriteLine($"Max price: {maxPrice:C}"); Console.WriteLine($"Min price: {minPrice:C}"); Console.WriteLine($"Total products: {totalProducts}"); // Element operations Console.WriteLine("\n=== ELEMENT OPERATIONS ==="); Product firstProduct = products.First(); Product lastProduct = products.Last(); Product singleElectronics = products.First(p => p.Category == "Electronics"); Product maybeProduct = products.FirstOrDefault(p => p.Price > 1000); Console.WriteLine($"First product: {firstProduct}"); Console.WriteLine($"Last product: {lastProduct}"); Console.WriteLine($"First electronics: {singleElectronics}"); Console.WriteLine($"Product over $1000: {(maybeProduct?.ToString() ?? "None")}"); // Set operations Console.WriteLine("\n=== SET OPERATIONS ==="); List<string> categories1 = new List<string> { "A", "B", "C" }; List<string> categories2 = new List<string> { "B", "C", "D" }; var union = categories1.Union(categories2); var intersect = categories1.Intersect(categories2); var except = categories1.Except(categories2); Console.WriteLine($"Union: {string.Join(", ", union)}"); Console.WriteLine($"Intersection: {string.Join(", ", intersect)}"); Console.WriteLine($"Difference: {string.Join(", ", except)}"); // Partitioning Console.WriteLine("\n=== PARTITIONING ==="); var firstThree = products.Take(3); var skipFirstThree = products.Skip(3); var page2 = products.Skip(3).Take(3); Console.WriteLine("First 3 products:"); firstThree.ToList().ForEach(p => Console.WriteLine($" - {p}")); Console.WriteLine("\nProducts after skipping first 3:"); skipFirstThree.ToList().ForEach(p => Console.WriteLine($" - {p}")); // Quantifiers Console.WriteLine("\n=== QUANTIFIERS ==="); bool hasExpensive = products.Any(p => p.Price > 500); bool allHaveStock = products.All(p => p.Stock > 0); bool containsLaptop = products.Any(p => p.Name == "Laptop"); Console.WriteLine($"Has expensive products: {hasExpensive}"); Console.WriteLine($"All products have stock: {allHaveStock}"); Console.WriteLine($"Contains laptop: {containsLaptop}"); } } }
Advanced LINQ and Performance
using System; using System.Collections.Generic; using System.Linq; using System.Diagnostics; namespace AdvancedLINQ { public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Major { get; set; } public double GPA { get; set; } public List<string> Courses { get; set; } public Student(int id, string name, int age, string major, double gpa) { Id = id; Name = name; Age = age; Major = major; GPA = gpa; Courses = new List<string>(); } public override string ToString() => $"{Name} ({Major}) - GPA: {GPA:F2}"; } class Program { static void Main() { var students = new List<Student> { new Student(1, "Alice", 20, "Computer Science", 3.8) { Courses = { "C#", "Algorithms", "Database" } }, new Student(2, "Bob", 22, "Mathematics", 3.2) { Courses = { "Calculus", "Statistics", "C#" } }, new Student(3, "Charlie", 21, "Physics", 3.9) { Courses = { "Physics", "Calculus", "Programming" } }, new Student(4, "Diana", 19, "Computer Science", 3.5) { Courses = { "C#", "Web Development", "Database" } }, new Student(5, "Eve", 23, "Mathematics", 3.7) { Courses = { "Statistics", "Algebra", "C#" } }, new Student(6, "Frank", 20, "Physics", 3.1) { Courses = { "Physics", "Calculus", "Chemistry" } }, new Student(7, "Grace", 22, "Computer Science", 3.9) { Courses = { "C#", "Algorithms", "AI" } } }; // Deferred Execution vs Immediate Execution Console.WriteLine("=== DEFERRED EXECUTION ==="); // This query is not executed yet var deferredQuery = students.Where(s => s.GPA > 3.5) .OrderByDescending(s => s.GPA) .Select(s => new { s.Name, s.GPA }); Console.WriteLine("Query defined but not executed yet"); // Execution happens here (when we iterate) Console.WriteLine("Executing query:"); foreach (var student in deferredQuery) { Console.WriteLine($" - {student.Name}: {student.GPA:F2}"); } // Immediate execution with ToList(), ToArray(), etc. var immediateResult = students.Where(s => s.Major == "Computer Science") .ToList(); // Executes immediately Console.WriteLine($"\nImmediate execution - CS students: {immediateResult.Count}"); // Complex queries with multiple from clauses (SelectMany) Console.WriteLine("\n=== SELECTMANY (FLATTENING) ==="); var allCourses = students.SelectMany(s => s.Courses) .Distinct() .OrderBy(course => course); Console.WriteLine("All unique courses:"); foreach (var course in allCourses) { Console.WriteLine($" - {course}"); } // Students and their courses var studentCourses = from student in students from course in student.Courses select new { student.Name, Course = course }; Console.WriteLine("\nStudents and their courses:"); foreach (var item in studentCourses.Take(5)) // Show first 5 { Console.WriteLine($" - {item.Name} takes {item.Course}"); } // GroupJoin (like SQL LEFT JOIN) Console.WriteLine("\n=== GROUPJOIN ==="); var majors = new List<string> { "Computer Science", "Mathematics", "Physics", "Chemistry" }; var studentsByMajor = from major in majors join student in students on major equals student.Major into studentGroup select new { Major = major, Students = studentGroup, Count = studentGroup.Count(), AverageGPA = studentGroup.Any() ? studentGroup.Average(s => s.GPA) : 0 }; foreach (var group in studentsByMajor) { Console.WriteLine($"\n{group.Major}:"); Console.WriteLine($" Count: {group.Count}, Average GPA: {group.AverageGPA:F2}"); foreach (var student in group.Students) { Console.WriteLine($" - {student.Name} ({student.GPA:F2})"); } } // Let clause for intermediate results Console.WriteLine("\n=== LET CLAUSE ==="); var studentAnalysis = from student in students let grade = student.GPA >= 3.7 ? "A" : student.GPA >= 3.3 ? "B" : student.GPA >= 2.7 ? "C" : "D" let status = student.Age >= 21 ? "Senior" : "Junior" select new { student.Name, student.Age, student.GPA, Grade = grade, Status = status }; foreach (var analysis in studentAnalysis) { Console.WriteLine($"{analysis.Name} ({analysis.Status}, Age {analysis.Age}): GPA {analysis.GPA:F2} -> {analysis.Grade}"); } // Performance considerations Console.WriteLine("\n=== PERFORMANCE ==="); var largeList = Enumerable.Range(1, 1000000).ToList(); var stopwatch = Stopwatch.StartNew(); // Inefficient: Multiple iterations var evenNumbers = largeList.Where(x => x % 2 == 0); var squared = evenNumbers.Select(x => x * x); var result1 = squared.ToList(); stopwatch.Stop(); Console.WriteLine($"Multiple operations: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); // Efficient: Chained operations var result2 = largeList.Where(x => x % 2 == 0) .Select(x => x * x) .ToList(); stopwatch.Stop(); Console.WriteLine($"Chained operations: {stopwatch.ElapsedMilliseconds}ms"); // PLINQ (Parallel LINQ) Console.WriteLine("\n=== PLINQ (PARALLEL LINQ) ==="); stopwatch.Restart(); var sequential = largeList.Where(x => x % 2 == 0) .Select(x => x * x) .ToList(); stopwatch.Stop(); Console.WriteLine($"Sequential: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); var parallel = largeList.AsParallel() .Where(x => x % 2 == 0) .Select(x => x * x) .ToList(); stopwatch.Stop(); Console.WriteLine($"Parallel: {stopwatch.ElapsedMilliseconds}ms"); // Custom LINQ methods Console.WriteLine("\n=== CUSTOM LINQ METHODS ==="); var topStudents = students.Where(s => s.GPA > 3.5) .OrderByDescending(s => s.GPA) .Take(3); Console.WriteLine("Top 3 students:"); foreach (var student in topStudents) { Console.WriteLine($" - {student}"); } // Pagination example int pageSize = 2; int pageNumber = 2; var page = students.OrderBy(s => s.Name) .Skip((pageNumber - 1) * pageSize) .Take(pageSize); Console.WriteLine($"\nPage {pageNumber} (size {pageSize}):"); foreach (var student in page) { Console.WriteLine($" - {student.Name}"); } } } }
6. Async Programming
Async/Await Fundamentals
using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using System.IO; namespace AsyncProgramming { public class AsyncDemo { // Basic async method public static async Task<string> DownloadWebsiteAsync(string url) { using (var client = new HttpClient()) { Console.WriteLine($"Starting download from {url}"); string content = await client.GetStringAsync(url); Console.WriteLine($"Download completed from {url}"); return content; } } // Async method with return value public static async Task<int> CalculateFactorialAsync(int n) { Console.WriteLine($"Starting factorial calculation for {n}"); // Simulate CPU-bound work await Task.Run(() => { for (int i = 1; i <= n; i++) { // Simulate work Task.Delay(10).Wait(); } }); int result = 1; for (int i = 2; i <= n; i++) { result *= i; } Console.WriteLine($"Factorial calculation completed for {n}"); return result; } // Multiple async operations public static async Task<List<string>> DownloadMultipleWebsitesAsync(List<string> urls) { var tasks = new List<Task<string>>(); foreach (string url in urls) { tasks.Add(DownloadWebsiteAsync(url)); } Console.WriteLine("All download tasks started..."); // Wait for all downloads to complete string[] results = await Task.WhenAll(tasks); Console.WriteLine("All downloads completed!"); return new List<string>(results); } // Async method with exception handling public static async Task<string> SafeDownloadAsync(string url) { try { using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(10); return await client.GetStringAsync(url); } } catch (HttpRequestException ex) { Console.WriteLine($"Network error: {ex.Message}"); return null; } catch (TaskCanceledException ex) { Console.WriteLine($"Request timeout: {ex.Message}"); return null; } } // Async file operations public static async Task WriteToFileAsync(string filePath, string content) { Console.WriteLine($"Starting file write to {filePath}"); // Ensure directory exists string directory = Path.GetDirectoryName(filePath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } await File.WriteAllTextAsync(filePath, content); Console.WriteLine($"File write completed: {filePath}"); } public static async Task<string> ReadFromFileAsync(string filePath) { if (!File.Exists(filePath)) { throw new FileNotFoundException($"File not found: {filePath}"); } Console.WriteLine($"Starting file read from {filePath}"); string content = await File.ReadAllTextAsync(filePath); Console.WriteLine($"File read completed: {filePath}"); return content; } // Cancellation support public static async Task LongRunningOperationAsync( int durationSeconds, System.Threading.CancellationToken cancellationToken = default) { Console.WriteLine($"Starting long operation for {durationSeconds} seconds"); for (int i = 1; i <= durationSeconds; i++) { // Check for cancellation cancellationToken.ThrowIfCancellationRequested(); Console.WriteLine($"Progress: {i}/{durationSeconds} seconds"); await Task.Delay(1000, cancellationToken); } Console.WriteLine("Long operation completed!"); } // Async properties and constructors (not allowed) // public async string AsyncProperty { get; set; } // Error! // Async event handlers public static async void ProcessButtonClick(object sender, EventArgs e) { try { Console.WriteLine("Button clicked - starting async processing"); await DownloadWebsiteAsync("https://example.com"); Console.WriteLine("Button click processing completed"); } catch (Exception ex) { Console.WriteLine($"Error in button click: {ex.Message}"); } } } // Async repository pattern public interface IUserRepository { Task<User> GetUserByIdAsync(int id); Task<List<User>> GetAllUsersAsync(); Task AddUserAsync(User user); Task UpdateUserAsync(User user); Task DeleteUserAsync(int id); } public class User { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } } public class MockUserRepository : IUserRepository { private readonly List<User> _users = new List<User> { new User { Id = 1, Name = "Alice", Email = "alice@example.com" }, new User { Id = 2, Name = "Bob", Email = "bob@example.com" }, new User { Id = 3, Name = "Charlie", Email = "charlie@example.com" } }; public async Task<User> GetUserByIdAsync(int id) { Console.WriteLine($"Getting user {id} from repository"); // Simulate database access delay await Task.Delay(100); return _users.Find(u => u.Id == id); } public async Task<List<User>> GetAllUsersAsync() { Console.WriteLine("Getting all users from repository"); await Task.Delay(200); return new List<User>(_users); } public async Task AddUserAsync(User user) { Console.WriteLine($"Adding user: {user.Name}"); await Task.Delay(150); _users.Add(user); } public async Task UpdateUserAsync(User user) { Console.WriteLine($"Updating user: {user.Name}"); await Task.Delay(150); var existingUser = _users.Find(u => u.Id == user.Id); if (existingUser != null) { existingUser.Name = user.Name; existingUser.Email = user.Email; } } public async Task DeleteUserAsync(int id) { Console.WriteLine($"Deleting user {id}"); await Task.Delay(100); _users.RemoveAll(u => u.Id == id); } } class Program { static async Task Main(string[] args) { Console.WriteLine("=== ASYNC/AWAIT DEMONSTRATION ===\n"); // Basic async call Console.WriteLine("1. Basic async download:"); string content = await AsyncDemo.DownloadWebsiteAsync("https://httpbin.org/json"); Console.WriteLine($"Downloaded {content?.Length ?? 0} characters\n"); // Multiple async operations Console.WriteLine("2. Multiple async operations:"); var urls = new List<string> { "https://httpbin.org/delay/1", "https://httpbin.org/delay/2", "https://httpbin.org/delay/1" }; var results = await AsyncDemo.DownloadMultipleWebsitesAsync(urls); Console.WriteLine($"Downloaded {results.Count} websites\n"); // Async with cancellation Console.WriteLine("3. Async with cancellation:"); using (var cts = new System.Threading.CancellationTokenSource()) { // Cancel after 3 seconds cts.CancelAfter(3000); try { await AsyncDemo.LongRunningOperationAsync(5, cts.Token); } catch (OperationCanceledException) { Console.WriteLine("Operation was cancelled!\n"); } } // File operations Console.WriteLine("4. Async file operations:"); string testFile = "test.txt"; await AsyncDemo.WriteToFileAsync(testFile, "Hello, async file operations!"); string fileContent = await AsyncDemo.ReadFromFileAsync(testFile); Console.WriteLine($"File content: {fileContent}\n"); // Repository pattern Console.WriteLine("5. Async repository pattern:"); IUserRepository userRepo = new MockUserRepository(); var users = await userRepo.GetAllUsersAsync(); Console.WriteLine($"Retrieved {users.Count} users"); var user = await userRepo.GetUserByIdAsync(1); Console.WriteLine($"Retrieved user: {user?.Name}\n"); // ValueTask example for performance Console.WriteLine("6. ValueTask for high-performance scenarios:"); await UseValueTaskExample(); Console.WriteLine("\nAll async operations completed!"); } static async ValueTask UseValueTaskExample() { // ValueTask is more efficient for synchronous completion var result = await GetCachedValueAsync(); Console.WriteLine($"ValueTask result: {result}"); } static async ValueTask<int> GetCachedValueAsync() { // If we have cached value, return synchronously if (DateTime.Now.Second % 2 == 0) // Simple cache simulation { return 42; // Synchronous completion } // Otherwise, perform async operation await Task.Delay(100); return 100; } } }
Advanced Async Patterns
using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using System.Linq; namespace AdvancedAsyncPatterns { // Async disposable pattern public class AsyncResource : IAsyncDisposable { private bool _disposed = false; public async Task ProcessDataAsync() { Console.WriteLine("Processing data asynchronously..."); await Task.Delay(1000); Console.WriteLine("Data processing completed"); } public async ValueTask DisposeAsync() { if (!_disposed) { Console.WriteLine("Disposing async resources..."); await Task.Delay(500); // Simulate async cleanup _disposed = true; Console.WriteLine("Async disposal completed"); } } } // Async lazy initialization public class AsyncLazy<T> { private readonly Func<Task<T>> _factory; private Lazy<Task<T>> _lazyTask; public AsyncLazy(Func<Task<T>> factory) { _factory = factory; _lazyTask = new Lazy<Task<T>>(() => _factory()); } public Task<T> Value => _lazyTask.Value; public bool IsValueCreated => _lazyTask.IsValueCreated; } // Async event with semaphore for thread safety public class AsyncEventPublisher { private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private event Func<string, Task> AsyncEvent; public async Task SubscribeAsync(Func<string, Task> handler) { await _semaphore.WaitAsync(); try { AsyncEvent += handler; } finally { _semaphore.Release(); } } public async Task UnsubscribeAsync(Func<string, Task> handler) { await _semaphore.WaitAsync(); try { AsyncEvent -= handler; } finally { _semaphore.Release(); } } public async Task PublishAsync(string message) { Func<string, Task> handlers; await _semaphore.WaitAsync(); try { handlers = AsyncEvent; } finally { _semaphore.Release(); } if (handlers != null) { var invocationTasks = handlers.GetInvocationList() .Cast<Func<string, Task>>() .Select(handler => handler(message)); await Task.WhenAll(invocationTasks); } } } // Async producer-consumer pattern public class AsyncProducerConsumer<T> { private readonly Queue<T> _queue = new Queue<T>(); private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(0); private readonly object _lock = new object(); private bool _completed = false; public void Produce(T item) { lock (_lock) { if (_completed) throw new InvalidOperationException("Production completed"); _queue.Enqueue(item); _semaphore.Release(); } } public async Task<T> ConsumeAsync(CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken); lock (_lock) { return _queue.Dequeue(); } } public void Complete() { lock (_lock) { _completed = true; } } } // Async streams (IAsyncEnumerable) - C# 8.0+ public static class AsyncStreams { public static async IAsyncEnumerable<int> GenerateNumbersAsync(int count) { for (int i = 1; i <= count; i++) { await Task.Delay(100); // Simulate async work yield return i; } } public static async IAsyncEnumerable<string> SimulateDataStreamAsync() { var dataPoints = new[] { "A", "B", "C", "D", "E" }; foreach (var point in dataPoints) { await Task.Delay(200); // Simulate async data arrival yield return point; } } public static async Task ProcessStreamAsync() { await foreach (var number in GenerateNumbersAsync(5)) { Console.WriteLine($"Received: {number}"); } } } // Task completion source for custom async operations public class AsyncOperation<T> { private readonly TaskCompletionSource<T> _tcs = new TaskCompletionSource<T>(); public Task<T> Task => _tcs.Task; public void SetResult(T result) => _tcs.SetResult(result); public void SetException(Exception exception) => _tcs.SetException(exception); public void SetCanceled() => _tcs.SetCanceled(); } // Retry pattern with exponential backoff public static class RetryHelper { public static async Task<T> RetryAsync<T>( Func<Task<T>> operation, int maxRetries = 3, TimeSpan initialDelay = default, Func<Exception, bool> shouldRetry = null) { if (initialDelay == default) initialDelay = TimeSpan.FromSeconds(1); var exceptions = new List<Exception>(); for (int retryCount = 0; retryCount <= maxRetries; retryCount++) { try { return await operation(); } catch (Exception ex) when (shouldRetry?.Invoke(ex) ?? true) { exceptions.Add(ex); if (retryCount == maxRetries) break; TimeSpan delay = TimeSpan.FromSeconds(Math.Pow(2, retryCount)) + initialDelay; Console.WriteLine($"Retry {retryCount + 1}/{maxRetries} after {delay}"); await Task.Delay(delay); } } throw new AggregateException("Operation failed after all retries", exceptions); } } class Program { static async Task Main(string[] args) { Console.WriteLine("=== ADVANCED ASYNC PATTERNS ===\n"); // Async disposable Console.WriteLine("1. Async Disposable Pattern:"); await using (var resource = new AsyncResource()) { await resource.ProcessDataAsync(); } Console.WriteLine(); // Async lazy Console.WriteLine("2. Async Lazy Initialization:"); var lazyValue = new AsyncLazy<string>(async () => { Console.WriteLine("Computing lazy value..."); await Task.Delay(1000); return "Lazy result"; }); Console.WriteLine("Accessing lazy value..."); string result = await lazyValue.Value; Console.WriteLine($"Lazy value: {result}\n"); // Async streams Console.WriteLine("3. Async Streams:"); await foreach (var item in AsyncStreams.GenerateNumbersAsync(3)) { Console.WriteLine($"Stream item: {item}"); } Console.WriteLine(); // Producer-consumer pattern Console.WriteLine("4. Async Producer-Consumer:"); var producerConsumer = new AsyncProducerConsumer<int>(); var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); _ = Task.Run(async () => { for (int i = 1; i <= 3; i++) { await Task.Delay(500); producerConsumer.Produce(i); Console.WriteLine($"Produced: {i}"); } producerConsumer.Complete(); }); try { while (true) { var item = await producerConsumer.ConsumeAsync(cts.Token); Console.WriteLine($"Consumed: {item}"); } } catch (OperationCanceledException) { Console.WriteLine("Consumption cancelled\n"); } // Retry pattern Console.WriteLine("5. Retry Pattern with Exponential Backoff:"); int attempt = 0; var retryResult = await RetryHelper.RetryAsync(async () => { attempt++; Console.WriteLine($"Attempt {attempt}"); if (attempt < 3) { throw new InvalidOperationException($"Simulated failure {attempt}"); } await Task.Delay(100); return "Success!"; }, maxRetries: 3); Console.WriteLine($"Retry result: {retryResult}\n"); // Task composition Console.WriteLine("6. Advanced Task Composition:"); await TaskCompositionExamples(); Console.WriteLine("All advanced async patterns demonstrated!"); } static async Task TaskCompositionExamples() { var tasks = new[] { Task.Delay(1000).ContinueWith(_ => "First"), Task.Delay(500).ContinueWith(_ => "Second"), Task.Delay(1500).ContinueWith(_ => "Third") }; // Wait for all tasks var allResults = await Task.WhenAll(tasks); Console.WriteLine($"WhenAll results: {string.Join(", ", allResults)}"); // Wait for any task var firstResult = await Task.WhenAny(tasks); Console.WriteLine($"WhenAny first result: {await firstResult}"); // ContinueWith for task chaining var complexTask = Task.Run(() => 10) .ContinueWith(t => t.Result * 2) .ContinueWith(t => $"Result: {t.Result}") .ContinueWith(t => t.Result.ToUpper()); Console.WriteLine($"Chained task result: {await complexTask}"); } } }
7. Web Development with ASP.NET
ASP.NET Core Web API
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using System.Collections.Generic; using System.Text.Json; // Minimal API example (ASP.NET Core 6.0+) var builder = WebApplication.CreateBuilder(args); // Add services to the container builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); // In-memory data store var users = new List<User> { new User(1, "John Doe", "john@example.com"), new User(2, "Jane Smith", "jane@example.com"), new User(3, "Bob Johnson", "bob@example.com") }; // API endpoints using minimal APIs app.MapGet("/api/users", () => Results.Ok(users)); app.MapGet("/api/users/{id}", (int id) => { var user = users.Find(u => u.Id == id); return user != null ? Results.Ok(user) : Results.NotFound(); }); app.MapPost("/api/users", (User user) => { user.Id = users.Count > 0 ? users.Max(u => u.Id) + 1 : 1; users.Add(user); return Results.Created($"/api/users/{user.Id}", user); }); app.MapPut("/api/users/{id}", (int id, User updatedUser) => { var existingUser = users.Find(u => u.Id == id); if (existingUser == null) return Results.NotFound(); existingUser.Name = updatedUser.Name; existingUser.Email = updatedUser.Email; return Results.Ok(existingUser); }); app.MapDelete("/api/users/{id}", (int id) => { var user = users.Find(u => u.Id == id); if (user == null) return Results.NotFound(); users.Remove(user); return Results.NoContent(); }); // Health check endpoint app.MapGet("/health", () => new { status = "Healthy", timestamp = DateTime.UtcNow }); // File upload endpoint app.MapPost("/api/upload", async (HttpRequest request) => { if (!request.HasFormContentType) return Results.BadRequest("Expected form data"); var form = await request.ReadFormAsync(); var file = form.Files["file"]; if (file == null || file.Length == 0) return Results.BadRequest("No file uploaded"); // Process the file var fileInfo = new { FileName = file.FileName, ContentType = file.ContentType, Size = file.Length, UploadedAt = DateTime.UtcNow }; return Results.Ok(fileInfo); }); app.Run(); // Record type for immutable data (C# 9.0+) public record User(int Id, string Name, string Email); // Traditional Controller-based API (for comparison) /* [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private static readonly List<User> _users = new(); [HttpGet] public IActionResult GetUsers() => Ok(_users); [HttpGet("{id}")] public IActionResult GetUser(int id) { var user = _users.Find(u => u.Id == id); return user != null ? Ok(user) : NotFound(); } [HttpPost] public IActionResult CreateUser(User user) { user.Id = _users.Count > 0 ? _users.Max(u => u.Id) + 1 : 1; _users.Add(user); return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user); } [HttpPut("{id}")] public IActionResult UpdateUser(int id, User updatedUser) { var existingUser = _users.Find(u => u.Id == id); if (existingUser == null) return NotFound(); existingUser.Name = updatedUser.Name; existingUser.Email = updatedUser.Email; return Ok(existingUser); } [HttpDelete("{id}")] public IActionResult DeleteUser(int id) { var user = _users.Find(u => u.Id == id); if (user == null) return NotFound(); _users.Remove(user); return NoContent(); } } */
MVC Pattern and Razor Pages
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; // MVC Controller example [Route("products")] public class ProductsController : Controller { private readonly IProductService _productService; public ProductsController(IProductService productService) { _productService = productService; } [HttpGet] public async Task<IActionResult> Index(string category = null, int page = 1) { var products = await _productService.GetProductsAsync(category, page, 10); var categories = await _productService.GetCategoriesAsync(); var viewModel = new ProductIndexViewModel { Products = products, Categories = categories, SelectedCategory = category, CurrentPage = page }; return View(viewModel); } [HttpGet("{id}")] public async Task<IActionResult> Details(int id) { var product = await _productService.GetProductByIdAsync(id); if (product == null) return NotFound(); return View(product); } [HttpGet("create")] public IActionResult Create() { return View(new ProductCreateModel()); } [HttpPost("create")] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(ProductCreateModel model) { if (!ModelState.IsValid) return View(model); var product = new Product { Name = model.Name, Description = model.Description, Price = model.Price, Category = model.Category }; await _productService.CreateProductAsync(product); return RedirectToAction(nameof(Index)); } [HttpGet("edit/{id}")] public async Task<IActionResult> Edit(int id) { var product = await _productService.GetProductByIdAsync(id); if (product == null) return NotFound(); var model = new ProductEditModel { Id = product.Id, Name = product.Name, Description = product.Description, Price = product.Price, Category = product.Category }; return View(model); } [HttpPost("edit/{id}")] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int id, ProductEditModel model) { if (id != model.Id) return BadRequest(); if (!ModelState.IsValid) return View(model); var product = await _productService.GetProductByIdAsync(id); if (product == null) return NotFound(); product.Name = model.Name; product.Description = model.Description; product.Price = model.Price; product.Category = model.Category; await _productService.UpdateProductAsync(product); return RedirectToAction(nameof(Index)); } [HttpPost("delete/{id}")] [ValidateAntiForgeryToken] public async Task<IActionResult> Delete(int id) { await _productService.DeleteProductAsync(id); return RedirectToAction(nameof(Index)); } } // Razor Pages example public class ProductDetailsModel : PageModel { private readonly IProductService _productService; public ProductDetailsModel(IProductService productService) { _productService = productService; } public Product Product { get; set; } public async Task<IActionResult> OnGetAsync(int id) { Product = await _productService.GetProductByIdAsync(id); if (Product == null) return NotFound(); return Page(); } public async Task<IActionResult> OnPostAddToCartAsync(int productId, int quantity) { var product = await _productService.GetProductByIdAsync(productId); if (product == null) return NotFound(); // Add to shopping cart logic TempData["Message"] = $"{product.Name} added to cart!"; return RedirectToPage("/Cart/Index"); } } // View Models public class ProductIndexViewModel { public List<Product> Products { get; set; } public List<string> Categories { get; set; } public string SelectedCategory { get; set; } public int CurrentPage { get; set; } public int TotalPages { get; set; } } public class ProductCreateModel { [Required] [StringLength(100)] public string Name { get; set; } [StringLength(500)] public string Description { get; set; } [Required] [Range(0.01, 10000)] public decimal Price { get; set; } [Required] public string Category { get; set; } } public class ProductEditModel { public int Id { get; set; } [Required] [StringLength(100)] public string Name { get; set; } [StringLength(500)] public string Description { get; set; } [Required] [Range(0.01, 10000)] public decimal Price { get; set; } [Required] public string Category { get; set; } } // Entity Framework Context public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Product> Products { get; set; } public DbSet<Category> Categories { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Product>(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Name).IsRequired().HasMaxLength(100); entity.Property(e => e.Price).HasColumnType("decimal(18,2)"); entity.HasIndex(e => e.Category); }); } } // Service interface public interface IProductService { Task<List<Product>> GetProductsAsync(string category = null, int page = 1, int pageSize = 10); Task<Product> GetProductByIdAsync(int id); Task<List<string>> GetCategoriesAsync(); Task CreateProductAsync(Product product); Task UpdateProductAsync(Product product); Task DeleteProductAsync(int id); } // Service implementation public class ProductService : IProductService { private readonly AppDbContext _context; public ProductService(AppDbContext context) { _context = context; } public async Task<List<Product>> GetProductsAsync(string category = null, int page = 1, int pageSize = 10) { var query = _context.Products.AsQueryable(); if (!string.IsNullOrEmpty(category)) { query = query.Where(p => p.Category == category); } return await query .OrderBy(p => p.Name) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); } public async Task<Product> GetProductByIdAsync(int id) { return await _context.Products.FindAsync(id); } public async Task<List<string>> GetCategoriesAsync() { return await _context.Products .Select(p => p.Category) .Distinct() .OrderBy(c => c) .ToListAsync(); } public async Task CreateProductAsync(Product product) { _context.Products.Add(product); await _context.SaveChangesAsync(); } public async Task UpdateProductAsync(Product product) { _context.Products.Update(product); await _context.SaveChangesAsync(); } public async Task DeleteProductAsync(int id) { var product = await _context.Products.FindAsync(id); if (product != null) { _context.Products.Remove(product); await _context.SaveChangesAsync(); } } } // Models public class Product { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; } public class Category { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } }
8. Database & Entity Framework
Entity Framework Core
using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace EFCoreExample { // DbContext - the main class that coordinates EF functionality public class BloggingContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<Tag> Tags { get; set; } public DbSet<Author> Authors { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer( @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { // Configure relationships and constraints modelBuilder.Entity<Blog>() .HasMany(b => b.Posts) .WithOne(p => p.Blog) .HasForeignKey(p => p.BlogId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity<Post>() .HasMany(p => p.Tags) .WithMany(t => t.Posts) .UsingEntity(j => j.ToTable("PostTags")); modelBuilder.Entity<Author>() .HasIndex(a => a.Email) .IsUnique(); // Seed data modelBuilder.Entity<Blog>().HasData( new Blog { BlogId = 1, Url = "http://blogs.msdn.com/dotnet", Rating = 5 }, new Blog { BlogId = 2, Url = "http://blogs.msdn.com/visualstudio", Rating = 4 }, new Blog { BlogId = 3, Url = "http://blogs.msdn.com/webdev", Rating = 3 } ); } } // Entity classes public class Blog { public int BlogId { get; set; } [Required] [MaxLength(200)] public string Url { get; set; } public int Rating { get; set; } // Navigation properties public List<Post> Posts { get; set; } = new List<Post>(); public Author Author { get; set; } public int? AuthorId { get; set; } } public class Post { public int PostId { get; set; } [Required] [MaxLength(200)] public string Title { get; set; } public string Content { get; set; } public DateTime PublishedOn { get; set; } public bool IsPublished { get; set; } // Foreign key public int BlogId { get; set; } // Navigation properties public Blog Blog { get; set; } public List<Tag> Tags { get; set; } = new List<Tag>(); } public class Tag { public int TagId { get; set; } [Required] [MaxLength(50)] public string Name { get; set; } // Navigation property (many-to-many) public List<Post> Posts { get; set; } = new List<Post>(); } public class Author { public int AuthorId { get; set; } [Required] [MaxLength(100)] public string Name { get; set; } [Required] [EmailAddress] public string Email { get; set; } public string Bio { get; set; } // Navigation property (one-to-one) public Blog Blog { get; set; } } // Repository pattern with EF Core public interface IBlogRepository { Task<Blog> GetBlogByIdAsync(int id); Task<List<Blog>> GetAllBlogsAsync(); Task<List<Blog>> GetBlogsByRatingAsync(int minRating); Task AddBlogAsync(Blog blog); Task UpdateBlogAsync(Blog blog); Task DeleteBlogAsync(int id); Task<bool> SaveChangesAsync(); } public class BlogRepository : IBlogRepository { private readonly BloggingContext _context; public BlogRepository(BloggingContext context) { _context = context; } public async Task<Blog> GetBlogByIdAsync(int id) { return await _context.Blogs .Include(b => b.Posts) .Include(b => b.Author) .FirstOrDefaultAsync(b => b.BlogId == id); } public async Task<List<Blog>> GetAllBlogsAsync() { return await _context.Blogs .Include(b => b.Posts) .Include(b => b.Author) .OrderBy(b => b.Url) .ToListAsync(); } public async Task<List<Blog>> GetBlogsByRatingAsync(int minRating) { return await _context.Blogs .Where(b => b.Rating >= minRating) .Include(b => b.Posts) .OrderByDescending(b => b.Rating) .ToListAsync(); } public async Task AddBlogAsync(Blog blog) { await _context.Blogs.AddAsync(blog); } public async Task UpdateBlogAsync(Blog blog) { _context.Blogs.Update(blog); } public async Task DeleteBlogAsync(int id) { var blog = await GetBlogByIdAsync(id); if (blog != null) { _context.Blogs.Remove(blog); } } public async Task<bool> SaveChangesAsync() { return await _context.SaveChangesAsync() > 0; } } // Service layer public class BlogService { private readonly IBlogRepository _blogRepository; public BlogService(IBlogRepository blogRepository) { _blogRepository = blogRepository; } public async Task<List<Blog>> GetPopularBlogsAsync(int minRating = 4) { return await _blogRepository.GetBlogsByRatingAsync(minRating); } public async Task<Blog> CreateBlogAsync(string url, int rating, string authorName, string authorEmail) { var blog = new Blog { Url = url, Rating = rating, Author = new Author { Name = authorName, Email = authorEmail } }; await _blogRepository.AddBlogAsync(blog); await _blogRepository.SaveChangesAsync(); return blog; } public async Task<bool> UpdateBlogRatingAsync(int blogId, int newRating) { var blog = await _blogRepository.GetBlogByIdAsync(blogId); if (blog == null) return false; blog.Rating = newRating; await _blogRepository.UpdateBlogAsync(blog); return await _blogRepository.SaveChangesAsync(); } } // Usage examples class Program { static async Task Main(string[] args) { // Setup DI container in real applications var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>(); optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True"); using var context = new BloggingContext(optionsBuilder.Options); // Ensure database is created await context.Database.EnsureCreatedAsync(); var repository = new BlogRepository(context); var blogService = new BlogService(repository); // CRUD operations Console.WriteLine("=== EF CORE DEMONSTRATION ===\n"); // Create var newBlog = await blogService.CreateBlogAsync( "https://example.com/blog", 5, "John Doe", "john@example.com"); Console.WriteLine($"Created blog: {newBlog.Url}"); // Read var blogs = await blogService.GetPopularBlogsAsync(4); Console.WriteLine("\nPopular blogs:"); foreach (var blog in blogs) { Console.WriteLine($" - {blog.Url} (Rating: {blog.Rating})"); } // Complex query with LINQ var postsWithTags = await context.Posts .Where(p => p.PublishedOn > DateTime.Now.AddMonths(-1)) .Include(p => p.Tags) .Include(p => p.Blog) .ThenInclude(b => b.Author) .OrderByDescending(p => p.PublishedOn) .ToListAsync(); Console.WriteLine("\nRecent posts with tags:"); foreach (var post in postsWithTags.Take(3)) { Console.WriteLine($" - {post.Title} by {post.Blog.Author?.Name}"); Console.WriteLine($" Tags: {string.Join(", ", post.Tags.Select(t => t.Name))}"); } // Raw SQL queries var highRatedBlogs = await context.Blogs .FromSqlRaw("SELECT * FROM Blogs WHERE Rating > {0}", 3) .Include(b => b.Posts) .ToListAsync(); // Transactions using var transaction = await context.Database.BeginTransactionAsync(); try { // Multiple operations in transaction context.Blogs.Add(new Blog { Url = "https://temp.com", Rating = 3 }); await context.SaveChangesAsync(); await transaction.CommitAsync(); } catch { await transaction.RollbackAsync(); throw; } Console.WriteLine("\nEF Core operations completed!"); } } }
Advanced EF Core and Performance
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using System.Diagnostics; namespace AdvancedEFCore { public class AdvancedBloggingContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } public DbSet<Author> Authors { get; set; } public DbSet<BlogStats> BlogStats { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer( @"Server=(localdb)\mssqllocaldb;Database=AdvancedBlogging;Trusted_Connection=True") .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information) .EnableSensitiveDataLogging(); } protected override void OnModelCreating(ModelBuilder modelBuilder) { // Configure owned types (value objects) modelBuilder.Entity<Author>().OwnsOne(a => a.Address); // Configure table-valued functions modelBuilder.HasDbFunction(typeof(AdvancedBloggingContext) .GetMethod(nameof(GetPopularPosts), new[] { typeof(int) })) .HasName("ufn_GetPopularPosts"); // Configure computed columns modelBuilder.Entity<Post>() .Property(p => p.Slug) .HasComputedColumnSql("LOWER(REPLACE(Title, ' ', '-'))", stored: true); // Configure concurrency tokens modelBuilder.Entity<Blog>() .Property(b => b.Version) .IsRowVersion(); // Configure query filters modelBuilder.Entity<Post>() .HasQueryFilter(p => p.IsPublished); } // Table-valued function mapping public IQueryable<Post> GetPopularPosts(int minLikes) => FromExpression(() => GetPopularPosts(minLikes)); } // Entity with owned type public class Author { public int AuthorId { get; set; } public string Name { get; set; } public string Email { get; set; } public Address Address { get; set; } public List<Blog> Blogs { get; set; } = new List<Blog>(); } // Owned type (value object) public class Address { public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string ZipCode { get; set; } public string Country { get; set; } } // Entity for keyless entity type (view/query) [Keyless] public class BlogStats { public int BlogId { get; set; } public string BlogUrl { get; set; } public int PostCount { get; set; } public int TotalLikes { get; set; } public DateTime LastPostDate { get; set; } } public class AdvancedBlogService { private readonly AdvancedBloggingContext _context; public AdvancedBlogService(AdvancedBloggingContext context) { _context = context; } // Explicit loading public async Task<Blog> LoadBlogWithPostsAsync(int blogId) { var blog = await _context.Blogs.FindAsync(blogId); if (blog != null) { // Explicitly load related data await _context.Entry(blog) .Collection(b => b.Posts) .Query() .Where(p => p.IsPublished) .LoadAsync(); await _context.Entry(blog) .Reference(b => b.Author) .LoadAsync(); } return blog; } // Change tracking examples public async Task DemonstrateChangeTracking() { var blog = await _context.Blogs.FirstAsync(); // Original values var originalUrl = _context.Entry(blog).OriginalValues["Url"]; var currentUrl = _context.Entry(blog).CurrentValues["Url"]; Console.WriteLine($"Original URL: {originalUrl}"); Console.WriteLine($"Current URL: {currentUrl}"); Console.WriteLine($"State: {_context.Entry(blog).State}"); Console.WriteLine($"Modified: {_context.Entry(blog).Property(b => b.Url).IsModified}"); // Detect changes _context.ChangeTracker.DetectChanges(); // Accept all changes _context.ChangeTracker.AcceptAllChanges(); } // Bulk operations with EF Core 7.0+ public async Task BulkUpdateBlogRatingsAsync(int oldRating, int newRating) { await _context.Blogs .Where(b => b.Rating == oldRating) .ExecuteUpdateAsync(setters => setters .SetProperty(b => b.Rating, newRating) .SetProperty(b => b.UpdatedAt, DateTime.UtcNow)); } public async Task BulkDeleteOldPostsAsync(DateTime cutoffDate) { await _context.Posts .Where(p => p.PublishedOn < cutoffDate && !p.IsPublished) .ExecuteDeleteAsync(); } // Complex query with multiple includes and filtering public async Task<List<Blog>> GetBlogsWithRecentPostsAsync(int days = 30) { var cutoffDate = DateTime.UtcNow.AddDays(-days); return await _context.Blogs .Include(b => b.Author) .Include(b => b.Posts .Where(p => p.PublishedOn >= cutoffDate && p.IsPublished) .OrderByDescending(p => p.PublishedOn) .Take(5)) .ThenInclude(p => p.Tags) .Where(b => b.Posts.Any(p => p.PublishedOn >= cutoffDate)) .OrderByDescending(b => b.Rating) .AsSplitQuery() // Prevents Cartesian explosion .ToListAsync(); } // Raw SQL with parameters public async Task<List<Blog>> SearchBlogsAsync(string searchTerm) { return await _context.Blogs .FromSqlRaw( "SELECT * FROM Blogs WHERE Url LIKE {0} OR BlogId IN (SELECT BlogId FROM Posts WHERE Title LIKE {1})", $"%{searchTerm}%", $"%{searchTerm}%") .Include(b => b.Posts) .ToListAsync(); } // Stored procedure execution public async Task<int> UpdateBlogStatisticsAsync(int blogId) { var result = await _context.Database .ExecuteSqlRawAsync("EXEC UpdateBlogStatistics @BlogId = {0}", blogId); return result; } // Performance optimization: AsNoTracking public async Task<List<Blog>> GetBlogsReadOnlyAsync() { return await _context.Blogs .AsNoTracking() // No change tracking - better performance for read-only .Include(b => b.Posts) .AsNoTrackingWithIdentityResolution() // EF Core 5.0+ .ToListAsync(); } // Global query filters public async Task<List<Post>> GetAllPostsIncludingUnpublishedAsync() { return await _context.Posts .IgnoreQueryFilters() // Bypass the IsPublished filter .ToListAsync(); } // Transaction with savepoints public async Task ComplexOperationWithSavepointsAsync() { using var transaction = await _context.Database.BeginTransactionAsync(); try { // Operation 1 _context.Blogs.Add(new Blog { Url = "https://blog1.com", Rating = 4 }); await _context.SaveChangesAsync(); // Create savepoint await transaction.CreateSavepointAsync("AfterBlog1"); // Operation 2 - might fail try { _context.Blogs.Add(new Blog { Url = null, Rating = 5 }); // This will fail await _context.SaveChangesAsync(); } catch { // Rollback to savepoint await transaction.RollbackToSavepointAsync("AfterBlog1"); } // Operation 3 - continues after rollback _context.Blogs.Add(new Blog { Url = "https://blog3.com", Rating = 3 }); await _context.SaveChangesAsync(); await transaction.CommitAsync(); } catch { await transaction.RollbackAsync(); throw; } } // Interceptors (EF Core 5.0+) public void DemonstrateInterceptors() { // In real applications, you'd register these in DbContext configuration // optionsBuilder.AddInterceptors(new MyCommandInterceptor(), new MyConnectionInterceptor()); } } // Performance benchmarking public class EFPerformanceBenchmark { private readonly AdvancedBloggingContext _context; public EFPerformanceBenchmark(AdvancedBloggingContext context) { _context = context; } public async Task MeasureQueryPerformanceAsync() { var stopwatch = Stopwatch.StartNew(); // Inefficient: N+1 query problem var blogs = await _context.Blogs.ToListAsync(); foreach (var blog in blogs) { var posts = await _context.Posts .Where(p => p.BlogId == blog.BlogId) .ToListAsync(); // This causes N additional queries! } stopwatch.Stop(); Console.WriteLine($"N+1 queries: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); // Efficient: Single query with Include var blogsWithPosts = await _context.Blogs .Include(b => b.Posts) .ToListAsync(); stopwatch.Stop(); Console.WriteLine($"Single query with Include: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); // More efficient: Filtered Include (EF Core 5.0+) var blogsWithRecentPosts = await _context.Blogs .Include(b => b.Posts.Where(p => p.IsPublished) .OrderByDescending(p => p.PublishedOn) .Take(5)) .ToListAsync(); stopwatch.Stop(); Console.WriteLine($"Filtered Include: {stopwatch.ElapsedMilliseconds}ms"); } } class Program { static async Task Main(string[] args) { var optionsBuilder = new DbContextOptionsBuilder<AdvancedBloggingContext>(); optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=AdvancedBlogging;Trusted_Connection=True"); using var context = new AdvancedBloggingContext(optionsBuilder.Options); await context.Database.EnsureCreatedAsync(); var service = new AdvancedBlogService(context); var benchmark = new EFPerformanceBenchmark(context); Console.WriteLine("=== ADVANCED EF CORE FEATURES ===\n"); // Demonstrate complex queries var blogs = await service.GetBlogsWithRecentPostsAsync(30); Console.WriteLine($"Found {blogs.Count} blogs with recent posts\n"); // Demonstrate performance await benchmark.MeasureQueryPerformanceAsync(); Console.WriteLine(); // Demonstrate change tracking await service.DemonstrateChangeTracking(); Console.WriteLine(); // Demonstrate bulk operations await service.BulkUpdateBlogRatingsAsync(3, 4); Console.WriteLine("Bulk update completed\n"); Console.WriteLine("Advanced EF Core features demonstrated!"); } } }
💻 Hands-On Practice Exercises
Beginner Level
- 1Create a console calculator that handles basic arithmetic operations
- 2Build a student grade management system with classes and objects
- 3Implement a simple bank account system with deposit/withdrawal functionality
- 4Create a temperature converter between Celsius and Fahrenheit
- 5Build a number guessing game with user input validation
Intermediate Level
- 1Develop a RESTful Web API for a todo list application
- 2Create a LINQ-based data analysis tool for sales data
- 3Build an ASP.NET Core MVC application for product catalog management
- 4Implement a file processing system with async/await operations
- 5Create a dependency injection container and demonstrate its usage
Advanced Level
- 1Build a full-stack e-commerce application with ASP.NET Core and Entity Framework
- 2Create a real-time chat application using SignalR
- 3Implement a microservices architecture with API Gateway pattern
- 4Build a machine learning model integration using ML.NET
- 5Create a high-performance data processing pipeline with parallel programming
🚀 Popular C# Frameworks & Technologies
ASP.NET Core
Cross-platform framework for building modern cloud-based web applications
- MVC Pattern
- Razor Pages
- Web API
- Dependency Injection
// Minimal API example var app = WebApplication.Create(args); app.MapGet("/", () => "Hello World!"); app.MapGet("/users/{id}", (int id) => $"User ID: {id}"); app.Run();
Entity Framework Core
Modern object-database mapper for .NET with LINQ support
- Code First
- Migrations
- LINQ Queries
- Change Tracking
// EF Core DbContext public class AppDbContext : DbContext { public DbSet<User> Users { get; set; } protected override void OnConfiguring( DbContextOptionsBuilder options) => options.UseSqlServer(connectionString); }
Blazor
Framework for building interactive web UIs using C# instead of JavaScript
- WebAssembly
- Server-side
- Components
- SignalR
// Blazor component <button @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Xamarin/.NET MAUI
Framework for building cross-platform mobile and desktop apps
- iOS & Android
- Windows & macOS
- Single Project
- Native UI
// MAUI ContentPage <ContentPage> <VerticalStackLayout> <Label Text="Welcome to .NET MAUI!" /> <Button Text="Click me" Clicked="OnCounterClicked" /> </VerticalStackLayout> </ContentPage>
🎯 C# Career Paths
Backend Developer
ASP.NET Core, Web APIs, Microservices, Cloud
Full-Stack Developer
C# + JavaScript/TypeScript, Blazor, React/Angular
Game Developer
Unity Engine, Game Logic, Performance Optimization
Continue Your C# Journey!
You've now explored the comprehensive landscape of C# programming, from basic syntax to advanced enterprise development patterns. C# continues to evolve with each version, bringing modern features and performance improvements.
The .NET ecosystem offers endless possibilities - explore cloud development with Azure, build cross-platform apps with MAUI, create games with Unity, or dive into machine learning with ML.NET.