Я не наверняка, как ControlCollection работ ASP.NET, поэтому возможно, кто-то может пролить некоторый свет на это для меня.
Я недавно обнаружил волшебство, которое является дополнительными методами и 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();
Нет, IEnumerable
не имеет много методов расширения: IEnumerable
does. Это два отдельных интерфейса, хотя IEnumerable
расширяет IEnumerable
.
Обычные способы преобразования в LINQ - это использование методов расширения Cast
и OfType
которые do расширяют негенерический интерфейс:
IEnumerable<TextBox> textBoxes = Controls.OfType<TextBox>();
IEnumerable<Control> controls = Controls.Cast<Control>();
Разница между ними в том, что OfType
просто пропустит все элементы, не имеющие требуемого типа; Cast
вместо этого выдаст исключение.
Как только вы получили ссылки на общий тип IEnumerable
, становятся доступны все остальные методы LINQ.
Это происходит потому, что класс ControlCollection
появился до появления дженериков; поэтому он реализует IEnumerable
, но не IEnumerable
.
К счастью, существует метод расширения LINQ для интерфейса IEnumerable
, который позволяет генерировать IEnumerable
через кастинг: Cast
. Что означает, что вы всегда можете просто сделать это:
var c = Controls.Cast<Control>().Where(x => x.ID == "Some ID").SingleOrDefault();
В дополнение к ответам, предоставленным Джоном Скитом и Дэном Тао, вы можете использовать синтаксис выражения запроса, явно указав тип.
Control myControl = (from Control control in this.Controls
where control.ID == "Some ID"
select control).SingleOrDefault();
Linq utilized Generic Collections. ControlsCollection implements IEnumerable
not IEnumberable
Если вы заметили, это не будет работать
((IEnumerable)page.Controls).Where(...
Однако, это работает
((IEnumerable<Control>)page.Controls).Where(...
Вы можете либо привести к Generic IEnumerable
, либо обратиться к методу расширения, который это делает, например так:
page.Controls.OfType<Control>().Where(c => c.ID == "Some ID").FirstOrDefault();