2013-05-15 71 views
2

例如,我想接受元素的通用列表作爲方法參數,並根據組成列表的對象的類型執行不同的操作。例如:如何檢查方法中通用對象的類型?

Private Sub DoStuff(Of T)(ByRef list As List(Of T) 
    If list.GetType() Is TypeOf(List(Of String) Then 
     'Do some string stuff 
    Else If list.GetType() Is TypeOf(List(Of Integer) Then 
     'Do some Integer stuff 
    End If 
End Sub 

如果有一種方法可以只看到的T的類型是什麼,這也將正常工作。我還試圖將我的論點設置爲List(Of ParentClass),看看它的TypeOf是否爲List(Of SubClass),但後來它說List(Of ParentClass)永遠不會是List(Of SubClass),這似乎沒有道理。

+0

基本上這樣做的背景是,我想轉換DataTable對象返回從DB在我的數據訪問層調用類型的表大約模型對象的列表。我認爲有一種方法可以執行此功能,這可能會很好。我也認爲最好避免在數據訪問層之外發送DataTable對象。什麼是最優雅的方式來完成這一點? – user2027080

回答

5

您可以比較通用型T,像這樣:

Private Sub DoStuff(Of T)(ByRef list As List(Of T)) 
    If GetType(T) = GetType(String) Then 
     'Do some string stuff 
    Else GetType(T) = GetType(Integer) Then 
     'Do some Integer stuff 
    End If 
End Sub 

或者,你甚至可以做到這一點作爲一個Select塊:

Private Sub DoStuff(Of T)(ByRef list As List(Of T)) 
    Select GetType(T) 
     Case GetType(String) 
      'Do some string stuff 
     Case GetType(Integer) 
      'Do some Integer stuff 
    End Select 
End Sub 

不言而喻的,但我想,我應該補充一點,檢查類型應該不鼓勵,並儘可能避免。做這樣的事情會導致雜亂的意大利麪代碼,並且它會破壞使用泛型參數的全部目的。通常,當你開始需要做這樣的事情時,這很好地表明你做得不好,你需要重新考慮你的設計。

List(Of ParentClass)List(Of SubClass)不匹配而言,這是人們對泛型的一種常見混淆。泛型工作的方式是,可爲泛型類型參數提供的每種可能類型將被視爲完全獨立的數據類型,與任何其他數據類型完全無關。因此,List(Of X)List(Of Y)被視爲完全不同的類型,無論XY可能共享的關係如何。換句話說,它本質上是短手爲創建新的類型,就像這樣:

Public Class ListOfSubClass 
    Inherits List(Of SubClass) 
End Class 

Public Class ListOfParentClass 
    Inherits List(Of ParentClass) 
End Class 

如果你這樣做,你不希望ListOfParentClass是兼容ListOfSubClass,因爲他們沒有任何關係彼此。以同樣的方式,你也不應該期望泛型也能以這種方式工作。

編輯

雖然我說的話有關不同類型相同的通用類之間的不兼容性鑄造是真實的,它不再是故事的全部。從Visual Studio 2010和框架的4.0版本開始,.NET支持協變和逆變,這有助於解決這個問題。有關更多信息,請參閱MSDN article

0

你能爲每種類型的通用列表創建一個具有相同名稱的擴展方法嗎?

C#一樣的東西:

var listOfStrings = new List<string>(); 
listOfStrings.DoStuff() //the extension method 

var listOfInts = new List<int>(); 
listOfInts.DoStuff() //the extension method 

擴展方法看起來是這樣的:

public static class listExtensions 
{ 
    public static void DoStuff(this IList<string> theList) 
    { 
     // Stuff with strings 
    } 
    public static void DoStuff(this IList<int> theList) 
    { 
     // Stuff with ints 
    } 
} 
6

如果您需要檢查泛型參數來確定代碼路徑,那麼你的方法不確實是通用的,這種情況應該使用過載方法來處理:

Private Sub DoStuff(ByRef list as List(Of String)) 
Private Sub DoStuff(ByRef list as List(Of Integer)) 

這同樣適用使用ParentClass和​​時 - 最具體的過載將被調用。

如果有共享的DoStuff,真正是通用的方面,這些提取到另一個助手方法。

這就是說,你可以檢查的T使用GetType(T)類型。