Pourquoi la collection Controls ne fournit-elle pas toutes les méthodes IEnumerable?
Je ne suis pas sûr de savoir comment le ControlCollection de ASP.Net fonctionne, alors peut-être que quelqu'un peut faire la lumière sur cela pour moi.
J'ai récemment découvert la magie qu'est les méthodes d'extension et Linq. Eh bien, j'étais très triste de constater que ce n'est pas une syntaxe valide
var c=Controls.Where(x => x.ID=="Some ID").SingleOrDefault();
Cependant, d'après ce que je peux dire, Controls
implémente l'interface IEnumerable
qui fournit de telles méthodes, alors qu'est-ce qui donne? Pourquoi n'est-elle pas juste travailler? J'ai trouvé un travail décent pour ce problème au moins:
var list = (IEnumerable<Control>)Controls;
var this_item = list.Where(x => x.ID == "Some ID").SingleOrDefault();
4 réponses
Non, IEnumerable
n'a pas beaucoup de méthodes d'extension: IEnumerable<T>
fait. Ce sont deux interfaces distinctes, bien que IEnumerable<T>
s'étende IEnumerable
.
Les méthodes normales de conversion de LINQ sont d'utiliser Cast<T>()
et OfType<T>()
méthodes d'extension quifont étendre l'interface non générique:
IEnumerable<TextBox> textBoxes = Controls.OfType<TextBox>();
IEnumerable<Control> controls = Controls.Cast<Control>();
La différence entre les deux est que OfType
ignorera simplement tous les éléments qui ne sont pas du type requis; Cast
lancera une exception à la place.
Une fois vous avez des références au type générique IEnumerable<T>
, tout le reste des méthodes LINQ sont disponibles.
C'est juste parce que le ControlCollection
la classe est venue avant les génériques; donc elle implémente IEnumerable
mais pas IEnumerable<Control>
.
Heureusement, il existe une extension LINQ méthode sur la IEnumerable
interface qui vous permet de générer un IEnumerable<T>
par moulage: Cast<T>
. Ce qui signifie que vous pouvez toujours faire ceci:
var c = Controls.Cast<Control>().Where(x => x.ID == "Some ID").SingleOrDefault();
En plus des réponses fournies par Jon Skeet et Dan Tao, vous pouvez utiliser la syntaxe d'expression de requête en fournissant explicitement le type.
Control myControl = (from Control control in this.Controls
where control.ID == "Some ID"
select control).SingleOrDefault();
Linq a utilisé des Collections génériques. ControlsCollection implémente IEnumerable
pas IEnumberable<T>
Si vous remarquez que cela ne fonctionnera pas
((IEnumerable)page.Controls).Where(...
Cependant, cela fait
((IEnumerable<Control>)page.Controls).Where(...
Vous pouvez soit convertir en Générique IEnumerable<T>
ou accéder à une méthode d'extension qui le fait, comme ceci:
page.Controls.OfType<Control>().Where(c => c.ID == "Some ID").FirstOrDefault();