UPDATE: Diese Antwort wurde 2011 geschrieben. Nach zwei Jahrzehnten, in denen Leute eine Kovarianz vom Rückgabetyp für C # vorgeschlagen haben, sieht es so aus, als würde sie endlich implementiert. Ich bin ziemlich überrascht. Die Ankündigung finden Sie unten unter https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ . Ich bin sicher, Details werden folgen.
Es hört sich so an, als ob Sie eine Kovarianz vom Rückgabetyp wünschen. C # unterstützt keine Kovarianz vom Rückgabetyp.
Bei der Kovarianz des Rückgabetyps überschreiben Sie eine Basisklassenmethode, die einen weniger spezifischen Typ zurückgibt, durch eine Methode, die einen spezifischeren Typ zurückgibt:
abstract class Enclosure
{
public abstract Animal Contents();
}
class Aquarium : Enclosure
{
public override Fish Contents() { ... }
}
Dies ist sicher, da Verbraucher von Inhalten über Beilage ein Tier erwarten und Aquarium verspricht, diese Anforderung nicht nur zu erfüllen, sondern darüber hinaus ein strengeres Versprechen abzugeben: dass das Tier immer ein Fisch ist.
Diese Art der Kovarianz wird in C # nicht unterstützt und wird wahrscheinlich nie unterstützt. Es wird von der CLR nicht unterstützt. (Es wird von C ++ und von der C ++ / CLI-Implementierung in der CLR unterstützt. Dazu werden magische Hilfsmethoden der unten vorgeschlagenen Art generiert.)
(Einige Sprachen unterstützen auch die Kontravarianz des formalen Parametertyps - Sie können eine Methode, die einen Fisch nimmt, mit einer Methode überschreiben, die ein Tier nimmt. Auch hier ist der Vertrag erfüllt. Die Basisklasse erfordert, dass jeder Fisch behandelt und der abgeleitete Die Klasse verspricht, nicht nur mit Fischen, sondern mit jedem Tier umzugehen. Ebenso unterstützen C # und die CLR keine Kontravarianz vom formalen Parametertyp.)
Sie können diese Einschränkung umgehen, indem Sie Folgendes tun:
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() { ... }
}
Jetzt haben Sie sowohl die Vorteile, eine virtuelle Methode zu überschreiben, als auch eine stärkere Eingabe, wenn Sie etwas vom Typ Aquarium zur Kompilierungszeit verwenden.