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