2014-05-21 76 views
0

我已經爲我的類型開發了一些序列化代碼。它們都共享一個通用接口來促進序列化邏輯。是否也可以將該接口添加到一些基本類型,如IntegerString,以便我可以將這些基本類型值中的一個傳入我的序列化邏輯並使其工作?我正在想象一些沿着擴展方法的東西,但添加一個接口而不是一個方法?我敢肯定,我可以想出一些方法來使用後期綁定,但如果可能的話,我想避免這種情況。是否可以將接口添加到現有類型?

+0

模糊的問題,你可能會想解釋越來越顯示出你的代碼 – stackunderflow

+0

爲什麼不使用擴展方法,你建議? –

+1

我希望能夠將對象作爲接口的實例傳遞給方法或集合。如果我通過擴展方法將它們作爲對象傳遞,則後期綁定對性能會產生相當嚴重的影響。此外,我一般不喜歡使用對象作爲類型,因爲我很迂腐。 –

回答

2

不可以擴展現有類型以使其實現接口(即將Implements IMyInterface添加到該類型代碼的頂部即可)。最接近的是創建一個將接口添加到基類的派生類。如果你覆蓋了CType運算符,你甚至可以創建它,所以值可以無縫地從一個類型轉換到另一個類型,而無需明確地轉換它們。但是,由於您提到StringInteger作爲您想要擴展的類型,這是不可能的。您無法創建從String繼承的新類型,因爲String被定義爲NotInheritable。同樣,您不能創建從Integer繼承的新類型,因爲IntegerStructure,而不是Class。結構不支持繼承。

因此,您擁有的最佳選擇是創建一個包裝核心值的新類,並通過實現接口來擴展它,然後重寫CType運算符,以便在覈心類型和包裝類型。舉例來說,假設你有一個這樣的接口:

Public Interface IWritable 
    Sub Write() 
End Interface 

,你不得不說了一個該類型的參數的方法,像這樣:

Private Sub TestWrite(writableObject As IWritable) 
    writableObject.Write() 
End Sub 

如果你需要一個Integer進入這個方法,你可以做一個包裝類是這樣的:

Public Class WritableInteger 
    Implements IWritable 

    Public Sub New(value As Integer) 
     Me.Value = value 
    End Sub 

    Public Property Value As Integer 

    Public Sub Write() Implements IWritable.Write 
     Console.Write(Value) 
    End Sub 

    Overloads Shared Widening Operator CType(value As Integer) As WritableInteger 
     Return New WritableInteger(value) 
    End Operator 

    Overloads Shared Widening Operator CType(value As WritableInteger) As Integer 
     Return value.Value 
    End Operator 
End Class 

由於CType運算符重載爲Widening,這意味着你可以共存在不投射的情況下顛倒兩種類型之間的值(即使使用Option Strict On)。舉例來說,這個工程:

Dim w As WritableInteger = New WritableInteger(5) 
Dim i As Integer = w 
w = i 

不幸的是,因爲TestWrite是要求一個IWritable而非WritableInteger,你不能只是調用TestWriteInteger,像這樣:

Dim i As Integer = 5 
TestWrite(5) 'This won't work! 

編譯器知道它需要將Integer轉換爲IWritable對象,但由於任何數量的類型都可以實現該接口,因此它不會自動嘗試確定它們中是否有任何一個爲此提供了一個CType運算符。由於可能有多種類型,允許從IntegerIWritable的轉換範圍擴大,它只是舉起手和哭聲。因此,即使擴展轉換已被聲明,您仍然必須在類似的情況下明確地轉換類型。例如:

Dim i As Integer = 5 
TestWrite(CType(i, WritableInteger)) 

或者更簡單地說:

Dim i As Integer = 5 
TestWrite(New WritableInteger(5)) 

你可以做的所有常見類型,將需要包裹創造重載更方便。例如,如果你創建了一個超負荷的TestWrite方法,像這樣:

Public Sub TestWrite(value As Integer) 
    TestWrite(New WritableInteger(value)) 
End Sub 

然後,你可以很容易地調用它是這樣的:

TestWrite(5) 

IWritable變量轉換回一個Integer,雖然,更加困難。例如:

Dim w As IWritable = New WritableInteger(5) 
Dim i As Integer = w ' This won't work! 
Dim i2 As Integer = CType(w, Integer) ' Whis won't work either! 

如果您需要做的是,你實際上必須首先將其轉換爲WritableInteger(並知道它是擺在首位的是類型的對象),例如:

Dim w As IWritable = New WritableInteger(5) 
If TypeOf w Is WritableInteger Then 
    Dim i As Integer = CType(w, WritableInteger) 
End If 

不幸的是,在保持編譯時類型檢查的安全性的同時,確實沒有辦法讓它更容易。最後還值得一提的是,如果你決定做一個這樣的包裝,並且無論包裝類型如何,接口的實現都是相同的,那麼你可以將它實現爲一個泛型類型,如下所示:

Public Class Writable(Of T) 
    Implements IWritable 

    Public Sub New(value As T) 
     Me.Value = value 
    End Sub 

    Public Property Value As T 

    Public Sub Write() Implements IWritable.Write 
     Console.Write(Value) 
    End Sub 

    Overloads Shared Widening Operator CType(value As T) As Writable(Of T) 
     Return New Writable(Of T)(value) 
    End Operator 

    Overloads Shared Widening Operator CType(value As Writable(Of T)) As T 
     Return value.Value 
    End Operator 
End Class 

然後,你可以調用TestWrite方法是這樣的:

TestWrite(New Writable(Of Integer)(5)) 
TestWrite(New Writable(Of String)("Hello World")) 
相關問題