наследник может уметь делать
что-то еще. Т.е. даункасты - когда нужно добатся до методов которые не описаны в контракте (те наследник умеет делать что-то, что не умеет делать родитель). Апкасты - когда нам наоборот нужно абстрагироватся от ненужных деталей
Например:
public interface IClass {
void DoSomething();
}
public class Class1: IClass {
public void DoSomething() { ... }
}
public class Class2: Class1{
public void DoSomethingFaster() { ... }
}
в этом примере оба класса могут делать полезную работу, но Class2 может сделать ее быстрее (но это не покрывает все случаи, потому просто использовать Class2 вместо Class1 не выйдет).
и дальше у нас может быть что-то такое:
...
public void InvokeWorker(IClass worker){
if (worker is Class2 class2Worker){
class2Worker.DoSomethingFaster()
}
else {
worker.DoSomething();
}
}
не то чтоб это было хорошим дизайном, но иногда бывает. в этом случае мы всегда сделаем работу хоть как-то, но в определенных случаях - мы можем сделать даункаст чтоб получить доступ к методам наследника (и сделать работу быстрее)