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:
- Delegate declaration and instantiation.
- Multicast delegates.
- Event publisher and subscriber patterns.
- Built-in delegate types like
ActionandFunc.
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:
- Improved application responsiveness.
- Efficient resource utilization.
- Simplified code structure compared to older asynchronous patterns.
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:
- Query syntax and method syntax.
- Deferred execution.
- Common operators like
Where,Select,OrderBy,GroupBy.
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:
- Type safety at compile time.
- Eliminates the need for boxing and unboxing.
- Increased code performance.
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:
- Dynamic loading of assemblies.
- Creating instances of types at runtime.
- Invoking methods dynamically.
- Inspecting metadata.
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}");