Frage

Ich versuche, ein 2 Tage auf abstrakte Methoden schlagen sich einpacken und Rückgabetyp Kovarianz, habe ich bereits zwei ähnliche Fragen geschrieben und ich bin ewig dankbar, dass die Gemeinschaft für die Informationen zur Verfügung gestellt, ich brauche nur noch eine letzte Push um die Ziellinie zu bekommen. Hier ist, was ich zu tun versuchen: 2 abstrakte Klassen, RecruiterBase und CandidateBase, beide haben concreate Implementierungen von RecruiterA und CandidateA. RecruiterBase hat eine abstrakte Methode alle rekrutierten Kandidaten Rückkehr IQueryable zu bekommen. Meine Implementierung von RecruiterA überschreibt den GetCandidates () -Methode IQueryable zurückzukehren.

public abstract class RecruiterBase
{ 
  // Constructors declared here

  public abstract IQueryable<CandidateBase> GetCandidates();
}

public abstract class CandidateBase
{  
  // Constructors declared here
}

und die Implementierungen:

public class CandidateA : CandidateBase
{
  // Constructors declared here
}

public class RecruiterA : RecruiterBase
{
  // Constructors declared here

  // ----HERE IS WHERE I AM BREAKING DOWN----
  public override IQueryable<CandidateA> GetCandidates()
  {
     return from c in db.Candidates
            where c.RecruiterId == this.RecruiterId
            select new CandidateA
            {
              CandidateId = c.CandidateId,
              CandidateName = c.CandidateName,
              RecruiterId = c.RecruiterId
            };
  }
}

Der Versuch, complile, die einen Kompilierung Fehler werfen, weil in meiner Implementierung von RecruitreBase die GetCandidates () Methode gibt IQueryable<CandidateA> statt IQueryable<CandidateBase>.

Nach nicht in der Lage zu sein, die Vorschläge aus einer früheren Frage zu bekommen ( Generika Rückkehr Arten von abstrakten / virtuellen Methoden ) zu arbeiten, habe ich viel mehr zu lesen, und kam in SO über die folgende Frage

Wie Subtyp in überschriebene Methode zurückzukehren die Unterklasse in C #?

Was mich schließlich machte klar, was ich hatte für die Suche ein Weg war Kovarianz für meine Rückkehr Typ zu implementieren. Früher habe ich Marc GRA des Schnipsel ...

abstract class BaseClass
{
    public BaseReturnType PolymorphicMethod()
    { return PolymorphicMethodCore();}

    protected abstract BaseReturnType PolymorphicMethodCore();
}

class DerivedClass : BaseClass
{
    protected override BaseReturnType PolymorphicMethodCore()
    { return PolymorphicMethod(); }

    public new DerivedReturnType PolymorphicMethod()
    { return new DerivedReturnType(); }
}

... als Grundlage für meine Lösung. So, jetzt meine RecruiterBase und RecruiterA Klassen wie folgt aussehen:

public abstract class RecruiterBase
{
  // Constructors declared here

  public IQueryable<CandidateBase> GetCandidates()
  {
     return GetCandidatesCore();
  }

  public abstract IQueryable<CandidateBase> GetCandidatesCore();
}

und meine Implementierung ...

public class RecruiterA : RecruiterBase
{
  // Constructors

  protected override IQueryable<CandidateBase> GetCandidatesCore()
  {
    return GetCandidates();
  }

  public new IQueryable<CandidateA> GetCandidates()
  {
    return from candidates in db.Candidates
           select new CandidateA
           {
             CandidateId = candidates.CandidateId,
             RecruiterId = candidates.RecruiterId
           };
  }
}

Ich habe gehofft, das würde mich endlich bekommen, was ich suchte, aber ich habe einen Fehler zur Kompilierzeit im folgenden Code, weil GetCandidates () kann nicht implizit CandidateA zu CandidateBase konvertieren:

  protected override IQueryable<CandidateBase> GetCandidatesCore()
  {
    return GetCandidates();
  }

so fügte ich eine Besetzung:

  protected override IQueryable<CandidateBase> GetCandidatesCore()
  {
    return ((IQueryable<CandidateBase>)GetCandidates());
  }

Alles kompiliert dann aber, wenn ich tatsächlich GetCandidates () aufrufen, in meinem Controller gibt es IQueryable<CandidateBase> statt IQueryable<CandidateA>. Also habe ich gleich wieder da bin, wo ich begann.

Wenn Sie machte es den ganzen Weg durch diese und Sie können mir helfen, ich werde Sie senden 12er Ihrer Lieblingsbier!

War es hilfreich?

Lösung

Justin Ich bin ein wenig verwirrt, warum Sie durch all die Mühe gehen.

Wenn Sie abstrakte Methode ist der Rückgabetyp IQueryable<CandidateBase> , dann ist das, was Sie bekommen. Ich sehe nicht ein Problem mit diesem, da Sie später immer noch werfen konnte zurück auf CandidateA oder CandidateB

Also, was genau wollen Sie erreichen? Vielleicht verstehen Ich bin nicht du Frage.

Bearbeiten hinzuzufügen:

Justin, was ist das?

public abstract class RecruiterBase<T>
    {
        // Constructors declared here

        public abstract IQueryable<CandidateBase> GetCandidates();
    }

    public abstract class CandidateBase
    {
        // Constructors declared here
    }


    public class CandidateA : CandidateBase
    {

    }

    public class RecruiterA : RecruiterBase<RecruiterA>
    {
        // Constructors declared here

        // ----HERE IS WHERE I AM BREAKING DOWN----
        public override IQueryable<CandidateBase> GetCandidates()
        {
            return db.Candidates.Where(cand => cand.RecruiterId == this.RecruiterId)
                         .Select(x => new CandidateA
                                          {
                                             CandidateId = c.CandidateId,
                                             CandidateName = c.CandidateName,
                                             RecruiterId = c.RecruiterId
                                           })
                         .Cast<CandidateBase>()
                         .AsQueryable();
        }
    }

Andere Tipps

Ich denke, Ihre Absichten sind gut, aber das Ergebnis ist, dass Sie den Punkt von polymorphen Code sind vermisst und auch den Wert zu verlieren.

Der Zweck mit Objekten von ihren abstrakten Typ oder durch ihre Schnittstellen zu arbeiten ist, mit dem Sie arbeiten lassen jeder konkrete Umsetzung, ohne wissen zu müssen alle konkrete Implementierungsdetails . Ich glaube, dein Glaube ist, dass Sie durch die Rückkehr konkrete Typen produzieren qualitativ höherwertigen Code, wenn in der Tat Sie beginnen den Wert der abstrakten Basisklasse zu negieren durch die Abstraktion zu verdecken.

Ein richtig gebaut Satz von abgeleiteten Klassen sollten nur sehr wenige Bedürfnisse müssen von ihren konkreten Arten angegangen werden; . Die abstrakte Klasse mit allen Implementierungen für die Arbeit und soll die überwiegende Mehrheit der Arbeit mit diesen Klassen behandeln sollte ausreichen - die Ausnahmen in der Minderheit sein sollten

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