如果调用 ToList 或 ToArray,为什么 C# 编译器允许在表达式树中使用动态操作
Why does C# compiler allow use of a dynamic operation in expression tree if ToList or ToArray is called
请注意:我知道有很多与此处讨论的主要错误消息相关,但我 找不到任何 post 讨论我的问题。
因此,在将其标记为重复之前,请阅读到最后。
一如既往,如果您能指出一个讨论我感到困惑的问题的问题,我很乐意记下这个问题。
我有一个方法 returns 如下所示的 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;
}
请注意,由于 table 的敏感性,我不得不删除 table 和列名。
问题:
我想从另一个 class 中得到 Value3 的总和。
private float getTargetScore()
{
return GetData().Sum(rec => Convert.ToSingle(rec.Value3));
}
这给了我以下编译器错误。
An expression tree may not contain a dynamic operation
令人困惑的部分:
如果在调用 Sum() 之前添加 .ToList() 或 .ToArray(),我不会收到此编译器错误
private float getTargetScore()
{
return GetData().ToArray().Sum(rec => Convert.ToSingle(rec.Value3));
}
我知道 .ToList() 或 .ToArray() 实现了查询(在这种情况下从数据库中获取数据)并导致 IEnumerable<> 而不是 IQueryable<> 但是为什么C# 编译器允许我在此处的表达式中使用动态操作?
注意:C#版本为4.0 (.Net 4.0)
在第一种情况下,您调用的是 IQueryable.Sum
public static int Sum<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, int>> selector)
在第二种情况下,您调用的是 IEnumerable.Sum
public static int Sum<TSource>(this IEnumerable<TSource> source,
Func<TSource, int> selector)
因此,在第一种情况下,编译器会尝试从 lambda 表达式创建一个 表达式树 ,但由于您使用的是动态的,因此无法执行此操作。
请注意:我知道有很多与此处讨论的主要错误消息相关,但我 找不到任何 post 讨论我的问题。
因此,在将其标记为重复之前,请阅读到最后。
一如既往,如果您能指出一个讨论我感到困惑的问题的问题,我很乐意记下这个问题。
我有一个方法 returns 如下所示的 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;
}
请注意,由于 table 的敏感性,我不得不删除 table 和列名。
问题:
我想从另一个 class 中得到 Value3 的总和。
private float getTargetScore()
{
return GetData().Sum(rec => Convert.ToSingle(rec.Value3));
}
这给了我以下编译器错误。
An expression tree may not contain a dynamic operation
令人困惑的部分:
如果在调用 Sum() 之前添加 .ToList() 或 .ToArray(),我不会收到此编译器错误
private float getTargetScore()
{
return GetData().ToArray().Sum(rec => Convert.ToSingle(rec.Value3));
}
我知道 .ToList() 或 .ToArray() 实现了查询(在这种情况下从数据库中获取数据)并导致 IEnumerable<> 而不是 IQueryable<> 但是为什么C# 编译器允许我在此处的表达式中使用动态操作?
注意:C#版本为4.0 (.Net 4.0)
在第一种情况下,您调用的是 IQueryable.Sum
public static int Sum<TSource>(this IQueryable<TSource> source,
Expression<Func<TSource, int>> selector)
在第二种情况下,您调用的是 IEnumerable.Sum
public static int Sum<TSource>(this IEnumerable<TSource> source,
Func<TSource, int> selector)
因此,在第一种情况下,编译器会尝试从 lambda 表达式创建一个 表达式树 ,但由于您使用的是动态的,因此无法执行此操作。