我为我的类型开发了一些序列化代码。它们共享一个通用接口以促进序列化逻辑。是否可以将该接口添加到某些基本类型,如Integer
或String
,这样我就可以将其中一个基本类型值传递给我的序列化逻辑并让它工作?我想象扩展方法的一些东西,但添加一个接口而不是一个方法?我确定我可以通过某种方式来设法使用后期绑定,但如果可能的话,我想避免这种情况。
答案 0 :(得分:2)
没有。无法扩展现有类型以使其实现接口(不能将Implements IMyInterface
添加到该类型的代码顶部,即)。最接近的是创建一个派生类,它将接口添加到基类。如果覆盖CType
运算符,您甚至可以创建它,以便可以将值从一种类型无缝转换为另一种类型而无需显式转换它们。但是,由于您提到了String
和Integer
作为要扩展的类型,因此甚至无法实现。您无法创建继承自String
的新类型,因为String
定义为NotInheritable
。同样,您无法创建继承自Integer
的新类型,因为Integer
是Structure
,而不是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
,因此您只能使用TestWrite
致电Integer
,像这样:
Dim i As Integer = 5
TestWrite(5) 'This won't work!
编译器知道它需要将Integer
转换为IWritable
对象,但由于任意数量的类型都可以实现该接口,因此它不会自动尝试找出是否存在他们为此提供CType
运算符。由于可能有多种类型允许将转化范围从Integer
扩展到IWritable
,因此它只会引起人们的愤怒。因此,即使声明了扩展转换,您仍然必须在类似的情况下显式转换类型。例如:
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"))