编译器错误:表达式树可能不包含动态操作

本文关键字:包含 动态 操作 错误 表达式 编译器 | 更新日期: 2023-09-27 18:34:19

请考虑以下代码,该代码包装(而不是出于特定原因使用继承)Dictionary<string, T>的实例,并实现IEnumerableIQueryable,以便它可以与 linq 查询一起使用:

public class LinqTest<T> : IEnumerable<KeyValuePair<string, T>>, IQueryable<KeyValuePair<string, T>>
{
    private Dictionary<string, T> items = default(Dictionary<string, T>);
    public virtual T this[string key]
    {
        get { return this.items.ContainsKey(key) ? this.items[key] : default(T); }
        set { this.items[key] = value; }
    }
    public virtual T this[int index]
    {
        get { return this[index.ToString()]; }
        set { this[index.ToString()] = value; }
    }
    public Type ElementType
    {
        get { return this.items.AsQueryable().ElementType; }
    }
    public Expression Expression
    {
        get { return this.items.AsQueryable().Expression; }
    }
    public IQueryProvider Provider
    {
        get { return this.items.AsQueryable().Provider; }
    }
    public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
    {
        return this.items.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.items.GetEnumerator();
    }
}

我按如下方式测试了这段代码:

LinqTest<dynamic> item = new LinqTest<dynamic>();
item["a"] = 45;
item["b"] = Guid.NewGuid();
item["c"] = "Hello World";
item["d"] = true;
item.Where(o => o.Value.GetType() == typeof(Guid)).ForEach(i => Console.WriteLine(i));
//Compiler error: An expression tree may not contain a dynamic operation

这向我表明o.Value.GetType() == typeof(Guid)无法编译到表达式中,因为它是dynamic .

但是,我使用以下代码测试了此理论:

Dictionary<string, dynamic> item = new Dictionary<string, dynamic>();
item["a"] = 45;
item["b"] = Guid.NewGuid();
item["c"] = "Hello World";
item["d"] = true;
item.Where(o => o.Value.GetType() == typeof(Guid)).ForEach(i => Console.WriteLine(i));

它可以编译和运行,没有任何错误,并包含一个动态表达式...任何人都可以解释一下,并可能指出我如何修复我的代码?

注意:.ForEach是一种非标准的扩展方法,它实现了foreach循环。

编译器错误:表达式树可能不包含动态操作

问题是您的类型实现了 IQueryable<> ,因此 Queryable 方法由成员查找选择 - 因此编译器尝试从您的 lambda 表达式创建表达式树...这就是失败的原因。

字典示例之所以成功,是因为它使用的是Enumerable而不是Queryable,因此它将 lambda 表达式转换为委托。

您可以使用AsEnumerable修复代码:

item.AsEnumerable()
    .Where(o => o.Value.GetType() == typeof(Guid))
    .ForEach(i => Console.WriteLine(i));

老实说,目前还不清楚为什么要实现IQueryable<> - 另一个更简单的选择就是停止这样做。您的源数据只是一个Dictionary,因此已经将使用 LINQ to Objects 而不是任何基于可查询的数据......为什么要介绍IQueryable<>