为什么c#编译器允许在调用ToList或ToArray时在表达式树中使用动态操作?

本文关键字:表达式 操作 动态 ToArray 编译器 调用 ToList 为什么 | 更新日期: 2023-09-27 18:02:56

请注意:我知道这里讨论的主要错误消息有许多相关,但我找不到任何讨论我问题的帖子。

因此,在将其标记为重复之前,请通读一遍。

和往常一样,如果你能指出一个问题来讨论我所困惑的问题,我很乐意把这个问题记下来。


我有一个方法返回如下的IQueryable

public IQueryable<dynamic> GetData(DateTime Start, DateTime End, Nullable<int> EmployeeId = null)
{
    var query = from T1 in Context.Table1
                join T2 in Context.Table2
                on T1.Col1 equals T2.Col1
                join T3 in Context.Table3
                on T2.Col1 equals T3.Col1
                where T1.Col1 == EmployeeId
                        && T1.Col2 >= Start
                        && T1.Col2 <= End
                select new
                {
                    Value1 = T1.Col1,
                    Value2 = T2.Col5,
                    Value3 = T3.Col7
                };
    return query;
}

请注意,由于表的敏感性,我不得不删除表和列名。

问题:

我想从另一个类中得到Value3的和

private float getTargetScore()
{
    return GetData().Sum(rec => Convert.ToSingle(rec.Value3));
}

这给了我下面的编译错误。

表达式树不能包含动态操作

令人困惑的部分:

如果在调用Sum()之前添加。tolist()或。toarray(),则不会得到此编译器错误

private float getTargetScore()
{
    return GetData().ToArray().Sum(rec => Convert.ToSingle(rec.Value3));
}

我理解。tolist()或。toarray()物化查询(在这种情况下从db中带来数据)并导致IEnumerable<>而不是IQueryable<> ,但为什么c#编译器允许我在这里使用表达式中的动态操作?

注意:c#的版本是4.0。Net 4.0)

为什么c#编译器允许在调用ToList或ToArray时在表达式树中使用动态操作?

在第一种情况下,你正在调用IQueryable。和

public static int Sum<TSource>(this IQueryable<TSource> source,
                                    Expression<Func<TSource, int>> selector)

在第二种情况下,调用IEnumerable。和

 public static int Sum<TSource>(this IEnumerable<TSource> source,
                                     Func<TSource, int> selector)

所以在第一种情况下,编译器试图创建一个表达式树从lambda表达式,是无法做到的,因为你使用动态