2010-07-21 8 views
26

Non sono sicuro di come funzioni la ControlCollection di ASP.Net, quindi forse qualcuno può far luce su questo per me.Perché la raccolta Controls non fornisce tutti i metodi IEnumerable?

Recentemente ho scoperto la magia che è i metodi di estensione e Linq. Beh, ero molto triste per scoprire che questa non è la sintassi valida

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

Tuttavia da quello che posso dire, Controls fa implementare l'interfaccia IEnumerable che fornisce tali metodi, in modo da ciò che dà? Perché non funziona? Ho trovato un lavoro dignitoso per questo problema almeno:

var list = (IEnumerable<Control>)Controls; 
var this_item = list.Where(x => x.ID == "Some ID").SingleOrDefault(); 
+0

Tu può fare 'list.SingleOrDefault (x => x.ID ==" Some ID ");' –

risposta

56

No, IEnumerable non ha molti metodi di estensione su di esso: IEnumerable<T> fa. Sono due interfacce separate, sebbene IEnumerable<T> si estenda IEnumerable.

I normali vie LINQ di conversione sono di usare i Cast<T>() e OfType<T>() estensione metodi che fanno estendere l'interfaccia non generica:

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

La differenza tra i due è che OfType sarà solo ignorare qualsiasi articoli che aren 't del tipo richiesto; Cast genererà invece un'eccezione.

Una volta ottenuti i riferimenti al tipo generico IEnumerable<T>, sono disponibili tutti i restanti metodi LINQ.

6

Questo è solo perché la classe ControlCollection è comparsa prima dei generici; quindi implementa IEnumerable ma non IEnumerable<Control>.

Fortunatamente, vi esiste un metodo di estensione LINQ sull'interfaccia IEnumerable che permette di generare un IEnumerable<T> attraverso casting: Cast<T>. Il che significa che si può sempre e solo fare questo:

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

Oltre alle risposte fornite da Jon Skeet e Dan Tao, è possibile utilizzare la sintassi di query, fornendo esplicitamente il tipo.

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

Linq ha utilizzato raccolte generiche. ControlsCollection implementa IEnumerable non IEnumberable<T>

Se si nota questo non funziona

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

Tuttavia, questo non fa

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

È possibile cast Generico IEnumerable<T> o accedere un metodo di estensione che fa, come so:

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