Концептуально я вижу простую разницу.
Интерфейс определяет ожидания для класса. Он заявляет, что разработчик должен обеспечить определенные поведения (методы, свойства, события). не предписывает, как класс должен работать, просто , что должно делать.
Абстрактный класс - это базовый класс, который не может быть создан самостоятельно. Обычно он обеспечивает частичную реализацию, которая может быть разделена между конкретными классами, производными от него. Таким образом, он предписывает как класс должен работать.
Это, в свою очередь, приводит к нескольким практическим различиям из-за языковых ограничений (например, C # не поддерживает множественное наследование, за исключением интерфейсов). Какой из них использовать, зависит от того, чего вы пытаетесь достичь.