Master inheritance, interfaces, and asynchronous programming patterns in C#.
Learn inheritance, interfaces, and modern async/await patterns.
Animal class and derived Dog and Cat classes.class Animal
{
public string Name { get; set; }
public Animal(string name)
{
Name = name;
}
// Virtual method - can be overridden
public virtual void Speak()
{
Console.WriteLine($"{Name} makes a sound.");
}
}
The virtual keyword allows derived classes to override this method.class Dog : Animal // Dog inherits from Animal
{
public Dog(string name) : base(name) { } // Call base constructor
public override void Speak() // Override the virtual method
{
Console.WriteLine($"{Name} barks: Woof!");
}
}
class Cat : Animal
{
public Cat(string name) : base(name) { }
public override void Speak()
{
Console.WriteLine($"{Name} meows: Meow!");
}
}
Use : base(name) to call the parent constructor.// Polymorphism: treat derived objects as base type
Animal[] animals = new Animal[]
{
new Dog("Rex"),
new Cat("Whiskers"),
new Animal("Unknown")
};
foreach (Animal animal in animals)
{
animal.Speak(); // Calls appropriate override!
}abstract class/methods when base shouldn't be instantiatedsealed prevents further inheritancebase.Method() calls parent implementationis and as for type checking: if (animal is Dog d) { }Rex barks: Woof!
Whiskers meows: Meow!
Unknown makes a sound.
class Dog : Animal { }public virtual void Speak() { }public override void Speak() { }public Dog(string name) : base(name) { }Animal[] animals = new Animal[] { new Dog("Rex") };Review feedback below
interface IShape
{
double GetArea(); // Method signature (no implementation)
double GetPerimeter();
string Name { get; } // Property signature
}
Interfaces define WHAT a class must do, not HOW. By convention, interface names start with "I".class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public string Name => "Rectangle";
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public double GetArea() => Width * Height;
public double GetPerimeter() => 2 * (Width + Height);
}
class Circle : IShape
{
public double Radius { get; set; }
public string Name => "Circle";
public Circle(double radius) { Radius = radius; }
public double GetArea() => Math.PI * Radius * Radius;
public double GetPerimeter() => 2 * Math.PI * Radius;
}IShape[] shapes = new IShape[]
{
new Rectangle(5, 3),
new Circle(4)
};
foreach (IShape shape in shapes)
{
Console.WriteLine($"{shape.Name}: Area = {shape.GetArea():F2}");
}class Foo : IBar, IBazRectangle: Area = 15.00, Perimeter = 16.00
Circle: Area = 50.27, Perimeter = 25.13
interface IShape { double GetArea(); }class Rectangle : IShape { }string Name { get; }public double GetArea() => Width * Height;Review feedback below
async/await to write non-blocking code that handles long-running operations efficiently.static async Task<string> FetchDataAsync()
{
Console.WriteLine("Starting fetch...");
// Simulate network delay (non-blocking)
await Task.Delay(2000); // 2 second delay
Console.WriteLine("Fetch complete!");
return "Data from server";
}
async marks the method as asynchronous. await pauses execution until the task completes without blocking the thread.// Returns a value
async Task<string> GetStringAsync() { ... }
// No return value
async Task DoWorkAsync() { ... }
// Fire and forget (use sparingly!)
async void EventHandler() { ... }static async Task Main() // async Main supported in C# 7.1+
{
Console.WriteLine("Program started");
// Await the async method
string result = await FetchDataAsync();
Console.WriteLine($"Result: {result}");
Console.WriteLine("Program ended");
}// Start multiple tasks
Task<string> task1 = FetchDataAsync();
Task<string> task2 = FetchDataAsync();
// Wait for all to complete
await Task.WhenAll(task1, task2);
// Or wait for any one
Task completedTask = await Task.WhenAny(task1, task2);async/await for I/O operationsasync void except for event handlersConfigureAwait(false) in library codeCancellationToken to cancel long operationsProgram started
Starting fetch...
Fetch complete!
Result: Data from server
Program ended
static async Task<string> FetchAsync() { }await Task.Delay(1000);return "result"; (automatically wrapped in Task)static async Task Main() { }string r = await FetchAsync();Review feedback below