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