抽象方法的协变返回类型的问题 [英] Problem with Covariant return types from an abstract method

查看:19
本文介绍了抽象方法的协变返回类型的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试结束对抽象方法和返回类型协方差的两天击败,我已经发布了两个类似的问题,我永远感谢社区提供的信息,我只需要最后一次推送到达终点线.这是我想要做的:2 个抽象类,RecruiterBase 和 CandidateBase,它们都具有 RecruiterA 和 CandidateA 的 concreate 实现.RecruiterBase 有一个抽象方法来让所有招聘的候选人返回 IQueryable.我的 RecruiterA 实现覆盖了 GetCandidates() 方法以返回 IQueryable.

I’m trying to wrap up a two day beat down on Abstract methods and return type Covariance, I’ve already posted two similar questions and I am eternally grateful to the community for the info provided, I just need one last push to get to the finish line. Here is what I am trying to do: 2 abstract classes, RecruiterBase and CandidateBase, both have concreate implementations of RecruiterA and CandidateA. RecruiterBase has an abstract method to get all recruited candidates returning IQueryable. My implementation of RecruiterA overrides the GetCandidates() method to return 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 而不是 IQueryable>.

Attempting to complile that throw a compile time error because in my implementation of RecruitreBase the GetCandidates() method returns IQueryable<CandidateA> instead of IQueryable<CandidateBase>.

在无法从上一个问题中获得建议后(通用返回类型从抽象/虚拟方法)到工作,我做了更多的阅读,并在SO中遇到了以下问题

After not being able to get the suggestions from a previous question (Generic return types from abstract/virtual methods) to work, I did a LOT more reading, and came across the following question in SO

如何在重写的方法中返回子类型C#中的子类?

这最终让我意识到我一直在寻找的是一种为我的返回类型实现协方差的方法.我使用了 Marc Gravell 的片段...

Which finally made me realize what I had been searching for was a way to implement Covariance for my return type. I used Marc Gravell's snippet...

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 类看起来像:

... as the basis for my solution. So now my RecruiterBase and RecruiterA classes look like:

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

我希望最终能得到我想要的东西,但我在以下代码中遇到了编译时错误,因为 GetCandidates() 无法将 CandidateA 隐式转换为 CandidateBase:

I was hoping that would finally get me what I was looking for but I got a compile time error in the following code because GetCandidates() cannot implicitly convert CandidateA to CandidateBase:

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

所以我添加了一个演员:

so I added a cast:

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

然后一切都会编译,但是当我在控制器中实际调用 GetCandidates() 时,它返回 IQueryable 而不是 IQueryable.所以我又回到了起点.

Everything then compiles but when I actually call GetCandidates() in my controller it returns IQueryable<CandidateBase> instead of IQueryable<CandidateA>. So I am right back where I started.

如果你完成了这一切并且你能帮助我,我会送你 12 包你最喜欢的啤酒!

If you made it all the way through this and you can help me I'll send you a 12 pack of your favorite beer!

推荐答案

Justin 我有点困惑为什么你需要经历所有这些麻烦.

Justin I am a little bit confused why you need to go through all that trouble.

如果您的抽象方法是返回类型 IQueryable 那么这就是您将得到的.我认为这没有问题,因为稍后您仍然可以将其转换回 CandidateACandidateB

If you abstract method is of return type IQueryable<CandidateBase> then that's what you'll get. I don't see a problem with this, since later on you could still cast it back to CandidateA or CandidateB

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

So what exactly are you trying to achieve? Maybe I am not understanding you question.

编辑添加:

贾斯汀,这个怎么样?

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

这篇关于抽象方法的协变返回类型的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆