协方差和orderby()问题

时间:2016-04-02 14:44:27

标签: c# expression-trees covariance

考虑以下代码

public class CommentBll : IBaseBllPersistor<Comment>
    {
     public List<Comment> GetData<TProp>(Expression<Func<Comment, TProp>> selector)
    {         
        using (var context = new WebsiteContext())
        { 
            var query = (from q in context.Comment
                        select new CommentDto
                        {
                            ExtraProp = q.Name+q.Id.ToString(),
                            PostDate = q.PostDate,
                        }).OrderBy(selector);
            return query.ToList();
        }            
    }
    public class  CommentDto: Comment
    {
        public string ExtraProp { get; set; }    
    }
}

 public  class Comment: IBaseModel
{
    public string CommentText { get; set; }
    public DateTime PostDate { get; set; }
}

当我从查询结尾删除此部分时

OrderBy(selector)

我收到此错误,

Error   CS0029  Cannot implicitly convert type System.Collections.Generic.List<CommentDto> to System.Collections.Generic.List<Comment>

我知道协方差,我知道错误是关于它但是为什么当我添加OrderBy(selector)时错误消失了?
有什么想法可能会发生这种情况吗?

2 个答案:

答案 0 :(得分:3)

  

为什么会发生这种情况的任何想法?

解释起来并不难。

让我们将您的查询分为两部分:

var queryA = (from q in context.Comment
              select new CommentDto
              {
                  ExtraProp = q.Name+q.Id.ToString(),
                  PostDate = q.PostDate,
              });
var query = queryA.OrderBy(selector);

queryA的类型为IQueryable<CommentDto>

现在,selector的第一个通用参数的类型是Comment。由于IQueryable<T>是协变的且Expression<TDelegate>是不变的,因此编译器满足第二个查询的唯一方法是将queryA威胁为IQueryable<Comment>,而不是{{1}的类型} {是query,最后的IOrderedQueryable<Comment>调用产生ToList

显然没有您List<Comment> OrderBy ToList queryA,结果为List<CommentDto>

在后一种情况下,IQueryable<T>的协方差可以通过简单明确指定ToList调用的泛型参数来轻松获得所需结果:

return queryA.ToList<Comment>();

答案 1 :(得分:0)

使用ToList()指定返回类型Comment,如下所述

 return query.ToList<Comment>();