Advanced C# Concepts - Textnotes

Advanced C# Concepts


Advanced concepts in C# allow for flexible, reusable, and concise code in modern applications.

1. Generics

Generics allow type-safe code without specifying exact data types.

1.1 Generic Class


class GenericClass<T>
{
public T Data { get; set; }

public void Display()
{
Console.WriteLine("Data: " + Data);
}
}

class Program
{
static void Main()
{
GenericClass<int> obj1 = new GenericClass<int> { Data = 100 };
obj1.Display();

GenericClass<string> obj2 = new GenericClass<string> { Data = "Hello" };
obj2.Display();
}
}

1.2 Generic Method


static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}

2. Delegates

Delegates are type-safe function pointers.


delegate int MathOperation(int a, int b);

class Program
{
static int Add(int x, int y) => x + y;
static int Multiply(int x, int y) => x * y;

static void Main()
{
MathOperation op = Add;
Console.WriteLine(op(5, 3)); // 8

op = Multiply;
Console.WriteLine(op(5, 3)); // 15
}
}

3. Events

Events allow publish-subscribe pattern for notifications.


using System;

class Publisher
{
public event Action OnChange;

public void RaiseEvent()
{
OnChange?.Invoke();
}
}

class Program
{
static void Main()
{
Publisher pub = new Publisher();
pub.OnChange += () => Console.WriteLine("Event triggered!");
pub.RaiseEvent();
}
}

4. Lambda Expressions

Concise syntax for anonymous methods.


Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(add(5, 10)); // 15

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var even = numbers.Where(n => n % 2 == 0);
Console.WriteLine(string.Join(", ", even)); // 2, 4

5. Anonymous Methods

Methods without a name; often used with delegates.


delegate void PrintMessage(string msg);

class Program
{
static void Main()
{
PrintMessage pm = delegate(string msg) { Console.WriteLine(msg); };
pm("Hello Anonymous Method");
}
}

6. Extension Methods

Add methods to existing types without modifying them.


static class StringExtensions
{
public static bool IsCapitalized(this string str)
{
if (string.IsNullOrEmpty(str)) return false;
return char.IsUpper(str[0]);
}
}

class Program
{
static void Main()
{
string name = "John";
Console.WriteLine(name.IsCapitalized()); // True
}
}

7. Indexers

Allow objects to be indexed like arrays.


class SampleCollection
{
private string[] data = new string[5];

public string this[int index]
{
get => data[index];
set => data[index] = value;
}
}

class Program
{
static void Main()
{
SampleCollection sc = new SampleCollection();
sc[0] = "Hello";
Console.WriteLine(sc[0]);
}
}

8. Nullable Types

Value types can be nullable using ?.


int? age = null;
if (age.HasValue)
Console.WriteLine(age.Value);
else
Console.WriteLine("Age is null");

Null-coalescing operator


int result = age ?? 18; // If age is null, use 18
Console.WriteLine(result);

9. Tuples

Tuples allow returning multiple values from a method.


(string, int) GetPerson()
{
return ("John", 25);
}

var person = GetPerson();
Console.WriteLine($"Name: {person.Item1}, Age: {person.Item2}");

// Named tuple
(string Name, int Age) person2 = ("Alice", 30);
Console.WriteLine($"Name: {person2.Name}, Age: {person2.Age}");

Summary of Chapter 10:

  1. Generics: Type-safe reusable code (GenericClass<T>, Generic Method).
  2. Delegates & Events: Function pointers & notifications.
  3. Lambda & Anonymous Methods: Concise inline methods.
  4. Extension Methods: Add functionality to existing types.
  5. Indexers: Object can be accessed like an array.
  6. Nullable Types: Handle null values for value types.
  7. Tuples: Return multiple values conveniently.