Error del compilador: un árbol de expresiones puede no contener una operación dinámica

c# compiler-errors dynamic expression-trees linq

Pregunta

Considere el siguiente código, que envuelve (en lugar de usar la herencia por razones específicas) una instancia de Dictionary<string, T> e implementa IQueryable e IEnumerable para que se pueda usar con consultas de 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();
    }
}

He probado este código de la siguiente manera:

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

Esto me indica que o.Value.GetType() == typeof(Guid) no se puede compilar en la expresión porque es dynamic .

Sin embargo, he probado esta teoría con el siguiente código:

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));

Esto compila y se ejecuta sin CUALQUIER error, y contiene una expresión dinámica ... ¿alguien puede explicarlo y posiblemente señalar cómo puedo arreglar mi código?

Nota: .ForEach es un método de extensión no estándar que implementa un bucle foreach.

Respuesta aceptada

El problema es que su tipo implementa IQueryable<> , por lo que el método Queryable es elegido por la búsqueda de miembros, por lo que el compilador intenta crear un árbol de expresiones a partir de su expresión lambda ... y eso es lo que falla.

El ejemplo del diccionario es Queryable porque utiliza Enumerable lugar de Queryable , por lo tanto, convierte la expresión lambda en un delegado.

Puedes arreglar tu código usando AsEnumerable :

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

Para ser honesto, no está claro por qué está implementando IQueryable<> , otra opción más simple sería simplemente dejar de hacer eso. Sus datos de origen son solo un Dictionary , por lo que ya vamos a usar LINQ to Objects en lugar de cualquier cosa basada en consultas ... ¿por qué introducir IQueryable<> ?



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow