考慮以下代碼,它包含(而不是使用繼承由於特定原因) Dictionary<string, T>
的實例,並實現IEnumerable
和IQueryable
以便它可以與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<>
呢?