UPDATE: Ta odpowiedź została napisana w 2011 roku. Po dwóch dekadach ludzi proponujących kowariancję typu zwracanego dla C # wygląda na to, że zostanie ostatecznie zaimplementowana; Jestem raczej zaskoczony. Zapowiedź znajduje się na dole strony https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ ; Jestem pewien, że pojawią się szczegóły.
Wygląda na to, że chcesz kowariancji typu zwracanego. C # nie obsługuje kowariancji typu zwracanego.
Kowariancja typu zwracanego polega na zastąpieniu metody klasy bazowej, która zwraca mniej szczegółowy typ, na taki, który zwraca bardziej szczegółowy typ:
abstract class Enclosure
{
public abstract Animal Contents();
}
class Aquarium : Enclosure
{
public override Fish Contents() { ... }
}
Jest to bezpieczne, ponieważ konsumenci Treści za pośrednictwem Obudowy oczekują zwierzęcia, a Akwarium obiecuje nie tylko spełnić ten wymóg, ale co więcej, złożyć bardziej rygorystyczną obietnicę: zwierzę jest zawsze rybą.
Ten rodzaj kowariancji nie jest obsługiwany w języku C # i jest mało prawdopodobne, aby kiedykolwiek był obsługiwany. Nie jest obsługiwany przez CLR. (Jest obsługiwany przez C ++ i przez implementację C ++ / CLI w CLR; robi to poprzez generowanie magicznych metod pomocniczych, które sugeruję poniżej.)
(Niektóre języki obsługują również kontrawariancję typu parametru formalnego - można przesłonić metodę pobierającą Fish metodą pobierającą Animal. Ponownie, kontrakt jest spełniony; klasa bazowa wymaga obsługi dowolnego Fisha, a pochodna class obiecuje nie tylko obsługiwać ryby, ale także dowolne zwierzęta. Podobnie, C # i CLR nie obsługują formalnej kontrawariancji typu parametru).
Aby obejść to ograniczenie, wykonaj następujące czynności:
abstract class Enclosure
{
protected abstract Animal GetContents();
public Animal Contents() { return this.GetContents(); }
}
class Aquarium : Enclosure
{
protected override Animal GetContents() { return this.Contents(); }
public new Fish Contents() { ... }
}
Teraz zyskujesz zarówno zalety zastępowania metody wirtualnej, jak i silniejsze pisanie podczas korzystania z czegoś w rodzaju Aquarium typu czasu kompilacji.