To paraphrase an overused example - and this isn't necessarily an example of good class design:
public class Employee
{
public string Name { get; set; }
public Guid EmployeeId { get; set; }
}
public class Manager : Employee
{
public IEnumerable<Employee> DirectReports { get; set; }
}
If you cast a Manager
as an Employee
var manager = GetManager(guid employeeId);
var employee = manager as Employee;
or
var employee = (Employee)manager;
You're not turning the Manager
into an Employee
, because the Manager
already is an Employee
.
In effect what you're saying is that you don't care what else this object is other than that it's an Employee
. Because in some cases you might not care. Suppose you want to create a list of employees - List<Employee>
- approaching their five-year anniversaries so that you can invite them to a party. It's important that you can add every sort of Employee
to that list.
That also enables polymorphism. Another common example:
public interface IAnimal
{
string MakeSound();
}
public class Cow : IAnimal
{
public string MakeSound()
{
return "Moo";
}
}
public class Giraffe : IAnimal
{
public string MakeSound()
{
return "I don't make any sound. Bad example.";
}
}
Now you can do this:
var animals = new List<IAnimal>();
animals.Add(new Cow());
animals.Add(new Giraffe());
foreach(var animal in animals) // or IAnimal in animals
{
Console.WriteLine(animal.MakeSound());
}
which would display
Moo
I don't make any sound. Bad example.
When you go through the items in your List<IAnimal>
you don't know what the actual class is for each. All you know is that each item is an IAnimal
and implements MakeSound()
. It doesn't change the "concrete" type for each one. It just means that for the purpose of what you're doing, you don't care about the concrete type.
This makes all sorts of things possible. You can have a class like this
public class Cow : IAnimal, ITastesGood
{
public string MakeSound()
{
return "Croak";
}
}
var cow = new Cow();
var animals = new List<IAnimal>();
var food = new List<ITastesGood>();
animals.Add(cow);
food.Add(cow);
The same instance of Cow
can be cast as any class it inherits from or any interface it implements.