我有一个实现Something
的课程ISomething
。如何从IQueryable<Something>
转换/转换为IQueryable<ISomething>
。当我尝试强制转换时,我能够编译,但是强制转换的结果总是为NULL。
背景:我这样做的原因是因为我的Something
类是CodeSmith生成的类(PLINQO模板),它具有表映射装饰,方法等。我的ISomething
接口是“POCO” “风格”,因为它是愚蠢的,只是反映了Something
类的属性。它也存在于它自己的命名空间中。我这样做,所以我不必从我的服务层引用保存Something
类的程序集。保存Something
类的程序集现在只需要在我的存储库层中引用。
答案 0 :(得分:11)
要了解这里发生了什么,从类型系统的角度来看这一点非常重要。对于类型系统,Something
和ISomething
是两种具有类似继承关系的类型(实现不是完全继承,而是关闭)。泛型类型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)