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();
いいえ、IEnumerable
には多くの拡張メソッドがありません:_IEnumerable<T>
_にはあります。 _IEnumerable<T>
_はIEnumerable
を拡張しますが、これらは2つの別個のインターフェースです。
変換の通常のLINQ方法は、 Cast<T>()
および OfType<T>()
拡張メソッドを使用することです。 )do非汎用インターフェースを拡張します:
_IEnumerable<TextBox> textBoxes = Controls.OfType<TextBox>();
IEnumerable<Control> controls = Controls.Cast<Control>();
_
2つの違いは、OfType
は必要なタイプではないアイテムをスキップするだけであるということです。 Cast
は代わりに例外をスローします。
一般的な_IEnumerable<T>
_タイプへの参照を取得すると、残りのすべてのLINQメソッドを使用できるようになります。
これは、 ControlCollection
クラスがジェネリックスの前に登場したからです。したがって、IEnumerable
を実装しますが、IEnumerable<Control>
は実装しません。
幸い、IEnumerable
インターフェイスにはLINQ拡張メソッドがあり、キャストによってIEnumerable<T>
を生成できます。 Cast<T>
。つまり、いつでもこれを行うことができます。
var c = Controls.Cast<Control>().Where(x => x.ID == "Some ID").SingleOrDefault();
JonSkeetとDanTaoによって提供された回答に加えて、型を明示的に指定することにより、クエリ式の構文を使用できます。
Control myControl = (from Control control in this.Controls
where control.ID == "Some ID"
select control).SingleOrDefault();
Linqはジェネリックコレクションを利用しました。 ControlsCollectionは、IEnumberable<T>
ではなくIEnumerable
を実装します
これが機能しないことに気付いた場合
((IEnumerable)page.Controls).Where(...
しかし、これは
((IEnumerable<Control>)page.Controls).Where(...
Generic IEnumerable<T>
にキャストするか、次のように拡張メソッドにアクセスできます。
page.Controls.OfType<Control>().Where(c => c.ID == "Some ID").FirstOrDefault();