I\'m not for sure how the ControlCollection of ASP.Net works, so maybe someone can shed some light on this for me.
I recently discovered the magic that is extension
Linq utilized Generic Collections. ControlsCollection implements IEnumerable
not IEnumberable<T>
If you notice this will not work
((IEnumerable)page.Controls).Where(...
However, this does
((IEnumerable<Control>)page.Controls).Where(...
You can either cast to Generic IEnumerable<T>
or access an extension method that does, like so:
page.Controls.OfType<Control>().Where(c => c.ID == "Some ID").FirstOrDefault();
No, IEnumerable
doesn't have many extension methods on it: IEnumerable<T>
does. They are two separate interfaces, although IEnumerable<T>
extends IEnumerable
.
The normal LINQ ways of converting are to use the Cast<T>() and OfType<T>() extension methods which do extend the nongeneric interface:
IEnumerable<TextBox> textBoxes = Controls.OfType<TextBox>();
IEnumerable<Control> controls = Controls.Cast<Control>();
The difference between the two is that OfType
will just skip any items which aren't of the required type; Cast
will throw an exception instead.
Once you've got references to the generic IEnumerable<T>
type, all the rest of the LINQ methods are available.
In addition to the answers provided by Jon Skeet and Dan Tao, you can use query expression syntax by explicitly providing the type.
Control myControl = (from Control control in this.Controls
where control.ID == "Some ID"
select control).SingleOrDefault();
This is just because the ControlCollection class came around before generics; so it implements IEnumerable
but not IEnumerable<Control>
.
Fortunately, there does exist a LINQ extension method on the IEnumerable
interface that allows you to generate an IEnumerable<T>
through casting: Cast<T>. Which means you can always just do this:
var c = Controls.Cast<Control>().Where(x => x.ID == "Some ID").SingleOrDefault();