在.net中,可以使用泛型,以便函数可以接受支持一个或多个接口的参数并从基类型派生,即使不存在所有有效参数类型派生的任何单一类型。例如,可以说:
Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(Param as T)
并允许传递SomeBaseType的任何衍生物,它实现了IInterface1和IInterface2。即使SomeBaseType不支持Interface1和Interface2,这也会起作用,并且实现这些接口的类不共享任何也实现它们的共同祖先。
如果在函数退出后不需要将参数保留在任何位置,这将非常方便。不幸的是,我无法找到一种方法来保持传入的参数,以便稍后可以传递给类似的函数,除非使用Reflection。有没有好办法呢?
我能够提出的最接近的是定义一个接口INest(可能不是最好的名字 - 任何人都可以改进吗?)因此:
Interface INest(Of Out T)
Function Nest() As T
End Interface
对于将与其他接口或基类“约束”结合使用的任何接口,定义一个通用版本,如下所示
Interface IFun1
' Any members of the interface go here, e.g. ...'
Sub DoFun1()
End Interface
Interface IFun1(Of Out T)
' This one does nothing but inherit'
Inherits IFun1, INest(Of T)
End Interface
支持多个接口的类应该声明自己实现泛型接口,并将自身作为类型参数。
Class test123a
Inherits sampleBase
Implements IFun1(Of test123a), IFun2(Of test123a), IFun3(Of test123a)
End Class
如果这样做,可以定义一个支持多个约束的函数参数或类变量:
Dim SomeField as IFun1(Of IFun2(Of IFun3(Of sampleBase)))
然后为它分配从sampleBase派生的任何类,它实现了这些接口。 SomeField将实现IFun1; SomeField.Nest将实现IFun2; SomeField.Nest.Nest将实现IFun3。请注意,除了从INest(Of T)继承的通用接口之外,不要求IFun1,IFun2,IFun3或sampleBase共享任何公共派生。还要注意,无论一个类实现了多少个INest派生接口,它只需要定义INest(Of T).Nest的一个实现。
不完全漂亮,但有两件好事:(1)实际上实现必要接口的任何具体类都可以直接分配给上面声明的字段,而不需要进行类型转换; (2)虽然以不同顺序链接类型的字段不是赋值兼容的,但它们可能相互转换。
有没有更好的方法以某种方式存储某些东西,以便它“已知”支持多个接口并从某种基类型派生?鉴于可以以类型安全的方式编写此类代码,如果编译器提供了一些帮助,那么.net 2.0 CLR似乎可能很好地支持这样的事情。不过,我不知道现有编译器有什么特别好的方法。
答案 0 :(得分:2)
我能想到的最好的方法是创建这个存储的抽象存储和通用实现。例如(原谅我的VB.NET):
MustInherit Class Storage
Public MustOverride Sub DoSomething()
End Class
Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
Inherits Storage
Public Overrides Sub DoSomething()
' do something with Value.
End Sub
Public Value As T
End Class
使用
Dim S As Storage
Sub Foo(Of T As {IInterface1, IInterface2, SomeBaseType})(ByVal Param As T)
S = New Storage(Of T) With {.Value = Param}
End Sub
Sub UseS()
S.DoSomething();
End Sub
更新:好的,因为我们可能无法事先确定所有行动:
MustInherit Class Storage
MustOverride ReadOnly Property SomeBaseType As SomeBaseType
MustOverride ReadOnly Property IInterface1 As IInterface1
MustOverride ReadOnly Property IInterface2 As IInterface2
End Class
Class Storage(Of T As {IInterface1, IInterface2, SomeBaseType})
Inherits Storage
Public Value As T
Public Overrides ReadOnly Property IInterface1 As IInterface1
Get
Return Value
End Get
End Property
Public Overrides ReadOnly Property IInterface2 As IInterface2
Get
Return Value
End Get
End Property
Public Overrides ReadOnly Property SomeBaseType As SomeBaseType
Get
Return Value
End Get
End Property
End Class