抽象方法的协变返回类型问题

2024-01-06

我正在尝试结束为期两天的关于抽象方法和返回类型协方差的讨论,我已经发布了两个类似的问题,我永远感谢社区提供的信息,我只需要最后一次推动即可到达终点线。这就是我想要做的:两个抽象类,RecruiterBase 和 CandidateBase,两者都有 RecruiterA 和 CandidateA 的具体实现。 RecruiterBase 有一个抽象方法来让所有招聘的候选人返回 IQueryable。我的 RecruiterA 实现重写了 GetCandidates() 方法以返回 IQueryable。

public abstract class RecruiterBase
{ 
  // Constructors declared here

  public abstract IQueryable<CandidateBase> GetCandidates();
}

public abstract class CandidateBase
{  
  // Constructors declared here
}

和实施:

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
            };
  }
}

尝试编译会引发编译时错误,因为在我的 RecruitreBase 实现中,GetCandidates() 方法返回IQueryable<CandidateA>代替IQueryable<CandidateBase>.

在无法从上一个问题中获得建议之后(抽象/虚拟方法的通用返回类型 https://stackoverflow.com/questions/1330473/generic-return-types-from-abstract-virtual-methods)为了工作,我做了很多阅读,并在 SO 中遇到了以下问题

如何在C#中子类的重写方法中返回子类型? https://stackoverflow.com/questions/421851/how-to-return-subtype-in-overridden-method-of-subclass-in-c

这最终让我意识到我一直在寻找的是一种为我的返回类型实现协方差的方法。我用了马克·格拉维尔的片段......

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(); }
}

...作为我的解决方案的基础。现在我的 RecruiterBase 和 RecruiterA 课程如下所示:

public abstract class RecruiterBase
{
  // Constructors declared here

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

  public abstract IQueryable<CandidateBase> GetCandidatesCore();
}

和我的实施...

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
           };
  }
}

我希望这最终能得到我想要的东西,但在以下代码中出现编译时错误,因为 Get Candidates() 无法将 CandidateS 隐式转换为 Candidate Base:

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

所以我添加了一个演员:

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

然后一切都会编译,但是当我实际在控制器中调用 GetCandidates() 时,它会返回IQueryable<CandidateBase>代替IQueryable<CandidateA>。所以我又回到了起点。

如果你能成功完成这一切并且可以帮助我,我将寄给你一瓶你最喜欢的 12 瓶啤酒!


贾斯汀,我有点困惑为什么你需要经历这些麻烦。

如果你的抽象方法是返回类型IQueryable<CandidateBase>那么这就是你会得到的。我不认为这有什么问题,因为稍后你仍然可以将其投射回候选人 or 候选人B

那么你到底想达到什么目的呢?也许我不明白你的问题。

编辑添加:

贾斯汀,这个怎么样?

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();
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

抽象方法的协变返回类型问题 的相关文章

随机推荐