2010-07-21 49 views
26

我不確定ASP.Net的ControlCollection是如何工作的,所以也許有人可以爲我闡明一些。爲什麼Controls集合不提供所有IEnumerable方法?

我最近發現了這個擴展方法和Linq的魔法。好吧,我很悲哀地發現這是無效的語法

var c=Controls.Where(x => x.ID=="Some ID").SingleOrDefault(); 

但是從我可以告訴,Controls確實實現了IEnumerable接口,它提供了這樣的方法,那麼怎麼辦?爲什麼這只是工作?我已經找到了這個問題一個體面的解決辦法,至少:

var list = (IEnumerable<Control>)Controls; 
var this_item = list.Where(x => x.ID == "Some ID").SingleOrDefault(); 
+0

你可以做'list.SingleOrDefault(x => x.ID ==「Some ID」);' – 2010-07-21 18:22:32

回答

56

不,IEnumerable上沒有它的許多擴展方法:IEnumerable<T>一樣。它們是兩個單獨的接口,儘管IEnumerable<T>延伸IEnumerable

轉換的正常LINQ的方法是使用Cast<T>()OfType<T>()擴展方法,其擴展非泛型接口:

IEnumerable<TextBox> textBoxes = Controls.OfType<TextBox>(); 
IEnumerable<Control> controls = Controls.Cast<Control>(); 

兩者之間的區別是,OfType將直接跳過這AREN任何項目所需的類型;相反,Cast會拋出異常。

一旦您參考了通用IEnumerable<T>類型,則所有其他的LINQ方法都可用。

6

這只是因爲ControlCollection類在泛型之前出現;所以它實現IEnumerable而不是IEnumerable<Control>

幸運的是,確實存在着一個LINQ擴展方法的IEnumerable接口,使您可以產生IEnumerable<T>通過鑄造於:Cast<T>。這意味着你可以永遠只是做到這一點:

var c = Controls.Cast<Control>().Where(x => x.ID == "Some ID").SingleOrDefault(); 
4

除了通過喬恩斯基特和丹道提供的答案,您可以通過顯式地提供類型使用查詢表達式語法。

Control myControl = (from Control control in this.Controls 
        where control.ID == "Some ID" 
        select control).SingleOrDefault(); 
1

Linq利用了泛型集合。 ControlsCollection實現IEnumerableIEnumberable<T>

如果你發現這是不行的

((IEnumerable)page.Controls).Where(... 

然而,這並不

((IEnumerable<Control>)page.Controls).Where(... 

您可以轉換爲普通IEnumerable<T>或訪問一個,喜歡的擴展方法所以:

page.Controls.OfType<Control>().Where(c => c.ID == "Some ID").FirstOrDefault(); 
相關問題