Advanced C# Concepts

Deep dive into the powerful and sophisticated features of the C# language.

Understanding C# Advanced Topics

C# is a versatile, object-oriented language that offers a rich set of features for building modern, robust applications. While the fundamentals are essential, mastering advanced concepts unlocks the true potential of C# for complex problem-solving and high-performance development.

Delegates and Events

Delegates are type-safe function pointers. They allow you to pass methods as arguments to other methods, assign methods to variables, and create callback mechanisms. Events are a way for a class to notify other classes when something of interest happens. They are typically implemented using delegates.

Key Concepts:

Consider this simple example:


public delegate void MyDelegate(string message);

public class Publisher {
    public event MyDelegate MyEvent;

    public void TriggerEvent(string msg) {
        MyEvent?.Invoke(msg);
    }
}

public class Subscriber {
    public void HandleEvent(string message) {
        Console.WriteLine($"Received: {message}");
    }
}

// Usage:
var publisher = new Publisher();
var subscriber = new Subscriber();
publisher.MyEvent += subscriber.HandleEvent;
publisher.TriggerEvent("Hello from the publisher!");
            

Asynchronous Programming with async and await

The async and await keywords simplify asynchronous programming, making it easier to write non-blocking code for I/O-bound operations, such as network requests or file access, without complex callback management.

Benefits:

Example:


public async Task FetchDataAsync(string url) {
    using (HttpClient client = new HttpClient()) {
        return await client.GetStringAsync(url);
    }
}

public async Task ProcessDataAsync() {
    string data = await FetchDataAsync("https://example.com/api/data");
    Console.WriteLine("Data fetched successfully!");
    // Process the data...
}
            

LINQ (Language Integrated Query)

LINQ provides a consistent, declarative syntax for querying data from various sources, including collections, databases, and XML documents. It offers a powerful way to filter, sort, and transform data.

Key Features:

Querying a list of numbers:


List<int> numbers = new List<int> { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var evenNumbers = from num in numbers
                  where num % 2 == 0
                  orderby num
                  select num;

foreach (var n in evenNumbers) {
    Console.Write(n + " "); // Output: 0 2 4 6 8
}
            

Generics

Generics enable you to create type-safe collections and methods that can operate on any data type without casting. This improves performance and code reusability.

Advantages:

A generic list example:


public class GenericList<T> {
    private List<T> _items = new List<T>();

    public void Add(T item) {
        _items.Add(item);
    }

    public T Get(int index) {
        return _items[index];
    }
}

// Usage:
var intList = new GenericList<int>();
intList.Add(10);
int y = intList.Get(0); // y is an int

var stringList = new GenericList<string>();
stringList.Add("Hello");
string s = stringList.Get(0); // s is a string
            

Reflection

Reflection allows you to inspect and manipulate types, methods, and properties at runtime. It's a powerful tool for building dynamic applications, serialization libraries, and unit testing frameworks.

Common Use Cases:

Getting type information:


Type stringType = typeof(string);
Console.WriteLine($"Name: {stringType.Name}"); // Output: Name: String

var methods = stringType.GetMethods();
Console.WriteLine($"Number of methods: {methods.Length}");