如何将IQueryable <something>作为IQueryable <isomething> </isomething> </something>返回

时间:2010-04-06 16:59:48

标签: .net linq casting interface iqueryable

我有一个实现Something的课程ISomething。如何从IQueryable<Something>转换/转换为IQueryable<ISomething>。当我尝试强制转换时,我能够编译,但是强制转换的结果总是为NULL。

背景:我这样做的原因是因为我的Something类是CodeSmith生成的类(PLINQO模板),它具有表映射装饰,方法等。我的ISomething接口是“POCO” “风格”,因为它是愚蠢的,只是反映了Something类的属性。它也存在于它自己的命名空间中。我这样做,所以我不必从我的服务层引用保存Something类的程序集。保存Something类的程序集现在只需要在我的存储库层中引用。

4 个答案:

答案 0 :(得分:11)

要了解这里发生了什么,从类型系统的角度来看这一点非常重要。对于类型系统,SomethingISomething是两种具有类似继承关系的类型(实现不是完全继承,而是关闭)。泛型类型IQueryable<Something>IQueryable<ISomething>没有这种关系。它们是两种完全不同的类型,属于继承树(包含IQueryable的分支)的完全不同的部分,而不是Something或ISomething。

因此,当从IQuerable<Something>投射到IQueryable<ISomething>时,就类型系统而言,您可能会尝试从IQueryable<double>投射到IQueryable<IDataRecord>。结果是一样的:它不知道如何进行转换,因此as运算符返回null。

这个问题的一个解决方案(不是问题本身,正如其他人所指出的)称为协方差是在C#4.0中实现的。 .Net Type Variance允许类型系统对专门使用相同泛型类型的两种不同类型之间的 specialization 关系有一定的了解,这样当从一个类型转换为另一个类型时,类型可以变化(注意这里的根词)。

对于.Net 4之前的代码,您必须使用类似.Cast<T>()扩展方法的内容。但这不太理想,因为它会强制进行真正的强制转换操作,其中类型差异允许框架使用已经存在的实际类型。

答案 1 :(得分:9)

您可以使用LINQ方法Cast

 IQueryable<Something> something = ...
 IQueryable<ISomething> casted = something.Cast<ISomething>();

答案 2 :(得分:1)

您在回答question时遇到的协方差问题有一个很好的解释。

答案 3 :(得分:0)

不是如何 - 而是为什么:

通用协方差 - 此链接有助于解释:

C# Generic Covariance