为什么Controls集合不提供所有IEnumerable方法?

时间:2010-07-21 18:17:50

标签: c# asp.net linq extension-methods ienumerable

我不确定ASP.Net的ControlCollection是如何工作的,所以也许有人可以为我阐明这一点。

我最近发现了扩展方法和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();

4 个答案:

答案 0 :(得分:71)

不,IEnumerable上没有很多扩展方法:IEnumerable<T>。它们是两个独立的界面,但IEnumerable<T>扩展IEnumerable

正常的LINQ转换方式是使用扩展非通用接口的Cast<T>()OfType<T>()扩展方法:

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

两者之间的区别在于OfType只会跳过任何不属于所需类型的项目; Cast会抛出异常。

一旦您获得了通用IEnumerable<T>类型的引用,所有其他LINQ方法都可用。

答案 1 :(得分:8)

这只是因为ControlCollection课程在仿制药之前出现了;所以它实现了IEnumerable但不是IEnumerable<Control>

幸运的是,IEnumerable界面上确实存在一个LINQ扩展方法,允许您通过强制转换生成 IEnumerable<T>Cast<T>。这意味着您可以随时执行此操作:

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

答案 2 :(得分:4)

除了Jon Skeet和Dan Tao提供的答案之外,您还可以通过明确提供类型来使用查询表达式语法。

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

答案 3 :(得分:2)

Linq使用了Generic Collections。 ControlsCollection实现IEnumerable而非IEnumberable<T>

如果您发现这不起作用

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

然而,这确实

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

你可以转换为Generic IEnumerable<T>或访问扩展方法,如下所示:

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