2017-05-04 105 views
0

我在繞過我遇到的問題時遇到了麻煩。我想將一些通用規則應用於結構,並且由於它們的類型不同,我想使用通用函數來執行此操作。我的問題是,通過只能使用指定類型的參數的方法來操作結構,我無法在沒有廣泛的轉換的情況下找到一種方法。見,例如,需要什麼樣的步驟來指定一個DateTime值應始終被指定爲UTC:將通用結構鑄造成其他結構

Public Shared Function Sanitize(Of T As Structure)(retValue As T?) As T? 
    ' If value is DateTime it must be specified as UTC: 
    If GetType(T) = GetType(DateTime) AndAlso retVal.HasValue Then 
     ' To specify the value as UTC, it must first be casted into DateTime, as it is not know to the compiler that the type in fact IS 
     ' DateTime, even if we just checked. 
     Dim retValAsObj = CType(retVal, Object) 
     Dim retValAsObjAsDateTime = CType(retValAsObj, DateTime) 
     Dim retValWithSpecifiedKind = DateTime.SpecifyKind(retValAsObjAsDateTime, DateTimeKind.Utc) 
     retVal = CType(CType(retValWithSpecifiedKind, Object), T?) 
    End If 
    Return retVal 
End Function 

我缺少的東西?爲這樣一個簡單的任務投四次似乎很複雜,因爲我是最好的/最簡單的解決方案。

+4

每當你看到自己寫這樣的代碼,那麼應該打開的燈泡是*這不是通用的*。隨着這種代碼剛剛變得複雜而痛苦的不可避免的結果。考慮利用vb.net對動態類型的體面支持,只要使用Option Strict Off,就可以使用'As Object'。 –

回答

0

您可以使用擴展方法
使用擴展方法,您不需要檢查類型並進行轉換。
隨着擴展方法,你將有自己的方法對每一種類型 - 維護簡單
隨着擴展方法,你將有「可讀」語法

<Extension> 
Public Shared Function Sanitize(Date? nullable) AS Date? 
{ 
    If nullable.HasValue = False Then Return nullable 
    Return DateTime.SpecifyKind(nullable.Value, DateTimeKind.Utc) 
} 

<Extension> 
Public Shared Function Sanitize(Integer? nullable) AS Integer? 
{ 
    If nullable.HasValue = False Then Return nullable 
    If nullable.Value < 0 Then Return 0 
    Return nullable.Value 
} 

某處在代碼

Dim sanitizedDate As Date? = receivedDate.Sanitize() 
Dim sanitizedAmount As Integer? = receivedAmount.Sanitize() 

擴展方法有一些缺點 - 例如,你不能「模擬」它們進行單元測試,這迫使你在每次使用時都測試「Sanitize」方法(如果你正在使用Test-First方法)。