【问题标题】:Need to cast explicitly thru anonymous type in Union()需要在 Union() 中通过匿名类型显式转换
【发布时间】:2011-10-16 15:03:18
【问题描述】:

我有 2 个变量/对象,通过这 2 个函数检索:

private IQueryable<Project> SelectAll_1(...)
{
    return query;
}

类项目是:

private int ID;
private string col1;
private string col2;
private string col3;

另一个:

private IQueryable<Project_test> SelectAll_2(...)
{
    return query;
}

其中的 POCO 是:

private string ID_inString;
private string col1;
private string col2;
private string col3;

我需要对他们两个都执行联合,

var P2 = SelectAll_2(...);
var P1 = SelectAll_1(...);

var P3 = P2.Union(P1);

但我得到一个错误,提到:

无法从用法中推断方法“System.Linq.Queryable.Union(System.Linq.IQueryable, System.Linq.Expressions.Expression>)”的类型参数。尝试明确指定类型参数。

我看到有人通过匿名类型解决它,但我不确定它是如何工作的。有人知道吗?

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    你不能联合两种不同的类型,除非一个继承自另一个(例如,你可以找到IEnumerable&lt;object&gt;IEnumerable&lt;string&gt;的联合,尽管这很少有用)。

    现在,在您的情况下,如果各种属性具有相同的含义,那么听起来 ProjectProject_test 确实应该是一种类型。目前,ID 属性有不同的类型——但这真的有必要或可取吗?如果它们都是具有相同范围的标识符,则将它们存储在相同的表示中是有意义的。如果属性具有相同的含义,则根本不应该在它们之间形成联合。如果它们确实具有相同的含义,则应尝试使两个序列使用相同的类型。

    可以为此使用匿名类型,方式如下:

    var projectedP1 = P1.Select(x => new { x.ID, x.col1, x.col2, x.col3 });
    var projectedP2 = P2.Select(x => new { ID = int.Parse(x.ID_inString),
                                                x.col1, x.col2, x.col3 });
    var union = projectedP1.Union(projectedP2);
    

    或者您可以只使用现有类型之一:

    var projectedP1 = P1.Select(x => new Project_test { 
                                         ID_inString = x.ID.ToString(), 
                                         col1 = x.col1, 
                                         col2 = x.col2, 
                                         col3 = x.col3 });
    var union = projectedP1.Union(P2);
    

    这不是很明显,其中哪一个是更好的主意 - 但如果可能的话,我会回到 尝试 来协调这两种类型,此时无论如何你都没有问题。

    【讨论】:

    • 谢谢,乔恩。创建一个新的 var 会导致任何性能问题,因为原来的 var 有点大??
    • @gan:不,不是。仅供参考,仅此而已。此外,LINQ 计算延迟 - 只是调用 Select 和 Where 等实际上并没有真正执行查询。
    • 谢谢。似乎没有编译错误,但运行时错误:查询包含对在不同数据上下文中定义的项目的引用。
    【解决方案2】:

    问题在于P2IQueryable&lt;Project&gt;P3IQueryable&lt;Project_test&gt;,您不能将它们合并为一个序列,因为它们属于不同类型。

    您需要做的是通过Select() 调用将它们都投影到一个通用类型中,据我所知必须是一个命名类型到 Jon Skeet 可以使用匿名类型来完成。定义匿名类型的初始化块必须具有相同数量的成员,具有相同的名称,以相同的顺序,具有相同的类型才能被视为一种类型。要使用 Select() 投影类型,您还需要将属性设为公共,以便 linq 方法可以访问。

    【讨论】:

    • 只要匿名类型构造表达式中的属性具有相同的名称、类型和顺序,它们就会映射到相同的类型。
    猜你喜欢
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多