2010-07-21 76 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();