Frage

Soweit ich weiß, dass es nicht möglich ist, die folgend in C # 2.0

zu tun
public class Father
{
    public virtual Father SomePropertyName
    {
        get
        {
            return this;
        }
    }
}

public class Child : Father
{
    public override Child SomePropertyName
    {
        get
        {
            return this;
        }
    }
}

ich umgehen das Problem, indem Sie die Eigenschaft in der abgeleiteten Klasse als „neu“ zu schaffen, aber das ist natürlich nicht polymorph.

public new Child SomePropertyName

Gibt es eine Lösung in 2.0? Was über alle Funktionen in 3.5, die diese Angelegenheit ansprechen?

War es hilfreich?

Lösung

Dies ist in jeder .NET-Sprache nicht möglich, da der Typ-Sicherheitsbedenken. In typsicheren Sprachen, müssen Sie Kovarianz für Rückgabewerte liefern und Kontra für Parameter. Nehmen Sie diesen Code ein:

class B {
    S Get();
    Set(S);
}
class D : B {
    T Get();
    Set(T);
}

Für die Get Verfahren bedeutet, dass die Kovarianz T müssen entweder S oder einen Typ von S ableiten. Andernfalls, wenn Sie einen Verweis auf ein Objekt vom Typ D haben in einer Variablen getippt B gespeichert, wenn Sie B.Get() genannt würden Sie ein Objekt nicht darstellbare als S zurück -. Die Art System zu brechen

Für die Set Methoden bedeutet, dass Kontra T muss entweder S sein oder eine Art, dass S aus leitet. Andernfalls, wenn Sie einen Verweis auf ein Objekt vom Typ D haben in einer Variablen getippt B gespeichert, wenn Sie B.Set(X) genannt, wo X vom Typ S war aber nicht vom Typ T, D::Set(T) würde ein Objekt eines Typs bekommt es nicht erwartet.

In C #, gab es eine bewusste Entscheidung, die Änderung der Art zu verbieten, wenn Eigenschaften Überlastung, auch wenn sie nur eine der Getter / Setter Paar, weil es sonst sehr inkonsistentes Verhalten haben würde ( "Du meinst, ich kann die Art mit einem Getter auf den einen ändern, aber nicht einen sowohl mit einem Getter und Setter Warum nicht " -?!?. Anonymous Alternate Universe Newbie)

Andere Tipps

Sie können wieder declare (neu), aber Sie können nicht wieder declare und Überschreibung zugleich (mit dem gleichen Namen). Eine Option ist eine geschützte Methode zu verwenden, um das Detail zu verbergen - dies ermöglicht sowohl Polymorphismus und versteckt zugleich:

public class Father
{
    public Father SomePropertyName
    {
        get {
            return SomePropertyImpl();
        }
    }
    protected virtual Father SomePropertyImpl()
    {
        // base-class version
    }
}

public class Child : Father
{
    public new Child SomePropertyName
    {
        get
        { // since we know our local SomePropertyImpl actually returns a Child
            return (Child)SomePropertyImpl();
        }
    }
    protected override Father SomePropertyImpl()
    {
        // do something different, might return a Child
        // but typed as Father for the return
    }
}

Nein, aber Sie können Generika in 2 verwenden und oben:

public class MyClass<T> where T: Person
{
    public virtual T SomePropertyName
    {
        get
        {
            return  ...;
        }
    }
}

Dann Vater und Kind sind generische Versionen der gleichen Klasse

Wikipedia :

  

In der Programmiersprache C #, Unterstützung für beide Rückgabetyp   Kovarianz und Parameter   Kontra für die Teilnehmer wurde hinzugefügt   in der Version 2.0 der Sprache.   Weder Kovarianz noch Kontra   sind für die Verfahren überwiegenden unterstützt.

Es ist ausdrücklich nicht sagen nichts über Kovarianz von Eigenschaften though.

Sie können eine gemeinsame Schnittstelle für Vater und Kind schaffen und eine Art dieser Schnittstelle zurück.

Nein. C # nicht über diese Idee unterstützen (es heißt „Rückgabetyp Kovarianz“). Sie können dies jedoch tun:

public class FatherProp
{
}

public class ChildProp: FatherProp
{
}


public class Father
{
    public virtual FatherProp SomePropertyName
    {
        get
        {
            return new FatherProp();
        }
    }
}


public class Child : Father
{
    public override FatherProp SomePropertyName
    {
        get
        {
            // override to return a derived type instead
            return new ChildProp();
        }
    }
}

d. verwenden, um den von der Basisklasse definiert Vertrag, aber das Rück einen abgeleiteten Typs. Ich habe eine detailliertere Probe gemacht diesen Punkt klarer zu machen -. Rückkehr „diese“ wieder würde nichts ändern

Es ist möglich (aber chaotisch) das zurückgegebene Objekt zu testen, es tatsächlichen Typen (dh „wenn someobject ChildProp ist“), aber es ist besser, eine virtuelle Methode auf es zu nennen, die das Richtige für seine Art des Fall ist.

Die Basisklasse virtuelle Methode (in diesem Fall, virtuelles Eigentum) nicht nur eine Implementierung hat, sondern definiert auch einen Vertrag: dass ein Kind Klasse eine andere Implementierung von SomePropertyName liefern kann, wenn sie diesen Vertrag erfüllt (dh SomePropertyName gibt ein Objekt vom Typ "FatherProp"). Wiederkehrende ein Objekt vom Typ „ChildProp“ abgeleitet von „FatherProp“ erfüllt diesen Vertrag. Aber man kann nicht den Vertrag in „Child“ ändern -. Dieser Vertrag gilt für alle Klassen von „Vater“ abstammen

Wenn Sie einen Schritt zurück und schauen Sie sich Ihr breiteres Design, gibt es andere Sprachkonstrukte in C # Toolkit, das Sie auch über statt denken sollen -. Generics oder Schnittstellen

  

Nein. C # ist diese Idee nicht unterstützen   (Es heißt „Rückgabetyp   Kovarianz ").

     

Aus Wikipedia:

     

In der Programmiersprache C #,   Unterstützung für beide Rückgabetyp   Kovarianz und Parameter   Kontra für die Teilnehmer wurde hinzugefügt   in der Version 2.0 der Sprache.   Weder Kovarianz noch Kontra   sind für die Verfahren überwiegenden unterstützt.

     

Sie können wieder declare (neu), aber Sie   kann bei dem nicht wieder erklären und außer Kraft setzen   Gleichzeitig (mit dem gleichen Namen). Ein   Option ist eine geschützte Methode zu verwenden, um   das Detail verbergen - dies ermöglicht sowohl   Polymorphismus und versteckt sich in der gleichen   Zeit:

Die besten Lösungen wären Generika zu verwenden:

public class MyClass<T> where T: Person
{
   public virtual T SomePropertyNameA
   {        
      get { return  ...; }    
   }
}//Then the Father and Child are generic versions of the same class

Dies ist die nächstgelegene ich kommen könnte (bisher):

    public sealed class JustFather : Father<JustFather> {}

    public class Father<T> where T : Father<T>
    { public virtual T SomePropertyName
        { get { return (T) this; }
        }
    }

    public class Child : Father<Child>
    { public override Child SomePropertyName
        { get { return  this; }
        }
    }

Ohne die JustFather Klasse konnte man keine Father<T> instanziiert, wenn es ein anderer abgeleiteten Typ ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top