C# 协方差和orderby()问题

C# 协方差和orderby()问题,c#,expression-trees,covariance,C#,Expression Trees,Covariance,考虑下面的代码 public class CommentBll : IBaseBllPersistor<Comment> { public List<Comment> GetData<TProp>(Expression<Func<Comment, TProp>> selector) { using (var context = new WebsiteContext())

考虑下面的代码

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; }
}
我得到这个错误

Error   CS0029  Cannot implicitly convert type System.Collections.Generic.List<CommentDto> to System.Collections.Generic.List<Comment>
错误CS0029无法将类型System.Collections.Generic.List隐式转换为System.Collections.Generic.List
我知道协方差,我知道错误是关于协方差的,但为什么我添加
OrderBy(selector)
时错误消失了?

知道为什么会发生这种情况吗?

用ToList()指定返回类型注释,如下所述

 return query.ToList<Comment>();
returnquery.ToList();
你知道为什么会这样吗

这不难解释

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

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

现在,
选择器的第一个泛型参数的类型是
注释
。由于
IQueryable
是协变的,而
表达式
是不变的,因此编译器满足第二个查询的唯一方法是将
queryA
作为
IQueryable
进行威胁,因为
query
的类型是
IOrderedQueryable
,最后的
ToList
调用生成
List

显然,没有您在
queryA
上调用的
OrderBy
列表,结果是
List

在后一种情况下,
IQueryable
的协方差允许通过明确指定
ToList
调用的通用参数,轻松获得所需的结果:

return queryA.ToList<Comment>();
返回queryA.ToList();

请显示完整的错误消息-它试图转换的类型。@JonSkeet我编辑了问题hmm。。。我希望即使使用
OrderBy
也会出现这种错误。我倾向于相信您使用的
OrderBy
不是
LINQ
方法,因为
OrderBy
不会更改
IEnumerable
/
IQueryable
的类型。您能告诉我们在这种情况下有效的
查询的类型吗?实际上,我很确定-因为
OrderBy(selector)
无法编译。您将无法将
表达式
传递给
OrderBy
,因为它需要
表达式
。不需要这样做。OP可以创建一个
列表
。但是当您返回列表时,返回类型是List,这就是为什么我建议将代码更改为实际返回一个
列表
——根据我的回答。我想签名是OP真正想要的。@MaheshChand我不能这么做啊,很好的发现。没有考虑过对
OrderBy
调用进行类型推断。Doh。您可能希望在不需要订购者时,只调用
ToList
的解决方案。@JonSkeet谢谢。实际上更有趣的是类似的情况,但是对于
IEnumerable
Func
,由于
Func
第一个参数的方差,结果根本不明显,因此这两个结果都是同样可能的。(C#6)编译器选择了与
IQueryable
/
表达式
相同的方法,但我不知道为什么。我不太明白你的意思,但是如果你提出一个新问题,并给出一个完整的示例(因此很容易讨论)我很乐意尝试将其刷新到规范中。但前提是你感到麻烦:)@JonSkeet不太可能-事实就是这样,我可以接受:)很高兴与你聊了一会儿:)
return queryA.ToList<Comment>();