Consider the following code, which wraps (rather than using inheritance for specific reasons) an instance of Dictionary<string, T>
and implements IEnumerable
and IQueryable
so that it can be used with linq queries:
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();
}
}
I tested this code as follows:
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
This indicates to me that o.Value.GetType() == typeof(Guid)
cannot be compiled into the expression because it is dynamic
.
However, I tested this theory with the following code:
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));
This compiles, and runs without ANY errors, and contains a dynamic expression...can anyone explain, and possibly point out how I can fix my code?
Note: .ForEach
is a non-standard extension method which implements a foreach loop.
The problem is that your type implements IQueryable<>
, so the Queryable
method is chosen by member lookup - so the compiler tries to create an expression tree from your lambda expression... and that's what fails.
The dictionary example succeeds because it's using Enumerable
rather than Queryable
, so it's converting the lambda expression into a delegate instead.
You can fix your code by using AsEnumerable
:
item.AsEnumerable()
.Where(o => o.Value.GetType() == typeof(Guid))
.ForEach(i => Console.WriteLine(i));
It's not clear why you're implementing IQueryable<>
at all, to be honest - another simpler option would simply be to stop doing that. Your source data is just a Dictionary
, so that's already going to be using LINQ to Objects instead of anything queryable-based... why introduce IQueryable<>
at all?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With