Herança Forçada VB.NET através de múltiplas gerações

Eu estou tentando envolver minha cabeça em herança / interfaces / implementação um pouco melhor no .net.

Eu tenho uma classe que é definida da seguinte forma (tipo de):

Public Class Sheet
    Property Name As String
    Property Steps As List(Of [Step])
End Class

A coisa é, [Step] é apenas uma classe base virtual. Existem 5 implementações concretas diferentes de [Step]. Para tornar as coisas um pouco mais complexas, existem 3 implementações DIRECT de [Step], 2 das quais são virtuais. Cada um desses 2 tem 2 subclasses que implementariam concretamente [Step].

Então, veja como fica:

                          Step
         |-----------------|-----------------|
         |                 |                 |
     SubStepA          SubStepB          SubStepC
    |----|----|                         |----|----|
    |         |                         |         |
SubStepAA SubStepAB                 SubStepCA SubStepCB

Então, SubStepB, SubStepAA, SubStepAB, SubStepCA e SubStepCB são as implementações concretas.

Há um par de coisas que eu gostaria de um passo para fazer, como Clone ().

Então, tentei declarar o seguinte no passo:

Public MustOverride Function Clone() As Step

O problema é que, quando tento implementar isso no SubStepAA, não posso declarar o seguinte:

Public Overrides Function Clone() As SubStepAA

Se eu fizer isso, recebo um erro dizendo que os tipos de retorno não são os mesmos.

A solução para isso é apenas usar uma chamada do DirectCast sempre que eu clonar uma subclasse concreta? Isso parece estranho e insatisfatório. Também parece errado. Quero dizer, se eu clonar um objeto SubStepAA, quero recuperar um objeto do tipo SubStepAA.

Tem que haver uma maneira de fazer isso, certo? Quer dizer, eu poderia apenas declarar cada classe do jeito que ela precisa ser, mas também parece errado ter que escrever 5 métodos DIFERENTES Clone () que apenas ACONTECER para trabalhar (essencialmente) da mesma maneira (criando uma cópia profunda do objeto referenciado).

Eu olhei para o uso de declarações de interface, mas isso parece sofrer do mesmo erro de incompatibilidade de tipo.

Por favor, me diga que eu estou sentindo falta de algo básico!

Obrigado!

Como um aparte, tenho feito algumas leituras e percebo que pode haver maneiras mais otimizadas de fazer cópias profundas de objetos (por exemplo, através de serialização / desserialização), mas ainda estou interessado nessa questão, mesmo que eu escolha clonar objetos usando uma abordagem diferente.