2011-01-24 52 views
5

我好興奮,在寫這篇泛型函數時,編譯器拋出一個錯誤(unable to cast T to System.Web.UI.Control我的第一個通用鑄造(C#)

我基本上把它傳遞一個類型時,我把它,它找的所有控件那種類型。錯誤發生在l.Add((T)ctrl);

private List<T> RecurseTypes<T>(Control ctrls) 
    { 
     var l = new List<T>(); 
     foreach (var ctrl in ctrls.Controls) 
      if (ctrl.GetType() is T) 
       l.Add((T)ctrl); 
     return l; 
    } 

我錯過了什麼,或者我只是運氣不好?

+0

凡爲T從哪裏來的存儲控制。讓我看看類聲明。 – 2011-01-24 13:39:03

+0

@Jannis:它不是來自一個類,這是一個通用*方法*:`RecurseTypes `。 – Ani 2011-01-24 13:39:59

+0

什麼行會引發異常? – Nickolodeon 2011-01-24 13:42:40

回答

13
private List<T> RecurseTypes<T>(Control parent) where T: Control 
{ 
    var l = new List<T>(); 
    foreach (var child in parent.Controls) 
     if (child is T) 
      l.Add((T)child); 
    return l; 
} 

2的變化:

  • 添加where T : Control通用的限制
  • 看到is使用(該控制可以是T,但GetType()回報Type,這是從未一個Control

另外,請注意,這並不真正遞歸;這可能只是:

return ctrl.Controls.OfType<T>().ToList(); 
0

你能給我們更多的細節嗎?

爲什麼不下面的代碼:

private List<T> RecurseTypes<T>(Control ctrl) 
    { 
     List<T> l = new List<T>(); 
     foreach (var ctrls in ctrl.Controls) 
     { 
      if (ctrls is T) 
       l.Add((T)ctrls); 
     } 
     return l; 
    } 
0

把一個約束會幫助你。

private List<T> RecurseTypes<T>(Control ctrls) where T : System.Web.UI.Control 
2

如果您使用的是.NET 3.5或更高版本,可以使用OfType<T>()Cast<T>()擴展方法,而不是寫你自己的。

OfType<T>()將返回能夠被投的初始集合的子集,而Cast<T>()將返回強制轉換爲所需類型的整個集合,但會拋出一個異常,如果集合中的一個元素不能被投。

0

也許T不是所需控件的類型。

我的意思是說,你不能確保你從控制轉換到T,其中T是???從Control繼承。

你需要的第一件事情就是添加通用約束:

private List<T> RecurseTypes<T>(Control ctrls) where T : Control 

然後,你不必爲了解一個線索,如果迭代控制是T.你需要檢查它是否是控制的一個子類:

if (ctrl.GetType().IsSubclassOf(typeof(Control)) 

最後,您現在可以假設的控件列表將是T類型