【问题标题】:How to return an IQueryable<Something> as an IQueryable<ISomething>如何将 IQueryable<Something> 作为 IQueryable<ISomething> 返回
【发布时间】:2011-02-04 21:56:43
【问题描述】:

我有一个实现ISomething 的类Something。如何从IQueryable&lt;Something&gt; 转换/转换为IQueryable&lt;ISomething&gt;。当我尝试强制转换时,我能够编译,但强制转换的结果始终为 NULL。

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

【问题讨论】:

    标签: .net linq casting interface iqueryable


    【解决方案1】:

    不是如何——而是为什么:

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

    C# Generic Covariance

    【讨论】:

    • 解释了答案,而不是为什么需要答案。你最好链接到 Eric Lippert 关于该主题的系列。
    • @Joel:你有这个系列的链接吗?
    • 对于整个系列,我没有一个好的链接可以提供。我知道这个 StackOverflow 答案上有一个索引:stackoverflow.com/questions/2184551/…
    【解决方案2】:

    你可以使用 LINQ 方法 Cast

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

    【讨论】:

      【解决方案3】:

      question 的答案中对您遇到的协方差问题进行了很好的解释。

      【讨论】:

        【解决方案4】:

        要了解这里发生了什么,从类型系统的角度来看这一点很重要。对于类型系统来说,SomethingISomething 是两个具有类继承关系的类型(实现不完全是继承,而是接近)。泛型类型IQueryable&lt;Something&gt;IQueryable&lt;ISomething&gt; 没有这种关系。它们是两种完全不同的类型,并且与Something 或ISomething 属于继承树(包括IQueryable 的分支)的完全不同的部分。

        所以当从IQuerable&lt;Something&gt; 转换为IQueryable&lt;ISomething&gt; 时,就类型系统而言,您不妨尝试从IQueryable&lt;double&gt; 转换为IQueryable&lt;IDataRecord&gt;。结果是一样的:它不知道如何进行转换,因此as 运算符返回 null。

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

        对于 .Net 4 之前的代码,您必须使用类似 .Cast&lt;T&gt;() 的扩展方法。但这不太理想,因为它强制进行真正的强制转换操作,其中类型变化让框架使用已经存在的实际类型。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多