you*_*hut 3 .net vb.net collections interface
我有一个实现IWeightable的Entity类:
Public Interface IWeightable
Property WeightState As WeightState
End Interface
Run Code Online (Sandbox Code Playgroud)
我有一个WeightCalculator类:
Public Class WeightsCalculator
Public Sub New(...)
...
End Sub
Public Sub Calculate(ByVal entites As IList(Of IWeightable))
...
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
遵循这个过程:
Dim entites As New List(Of Entity)Dim
wc As New WeightsCalculator(...)为什么我不能做wc.Calculate(实体)?我收到:
无法转换类型为'System.Collections.Generic.List
1[mynameSpace.Entity]' to type 'System.Collections.Generic.IList1 [myNamespace.IWeightable]'的对象.
如果实体实现IWeightable,为什么这不可能?
这不起作用.
假设您有一个不同的类,OtherEntity它也将实现该接口.如果您的上述代码可以使用,该方法Calculate可以添加OtherEntity您的列表的实例Entity:
Dim entities As New List(Of Entity)()
Dim weightables As List(Of IWeightable) = entities ' VB forbids this assignment!
weightables.Add(New OtherEntity())
Run Code Online (Sandbox Code Playgroud)
这是非法的.如果不是,那么内容会entities(0)是什么?
要使代码工作,请使用带约束的泛型方法:
Public Sub Calculate(Of T As IWeightable)(ByVal entites As IList(Of T))
...
End Sub
Run Code Online (Sandbox Code Playgroud)
A List(Of Entity)不是IList(Of IWeightable).考虑这段代码(其中的OtherWeightable实现IWeightable):
Dim list As IList(Of IWeightable) = New List(Of Entity)
list.Add(new OtherWeightable)
Run Code Online (Sandbox Code Playgroud)
编译的第二行 - 没有什么可疑的 - 但你不想要一个OtherWeightable元素List(Of Entity).
.NET 4 以泛型方差的形式对此进行了部分解决.如果您的方法只迭代,您可以将签名更改为:Calculateentities
Public Sub Calculate(ByVal entites As IEnumerable(Of IWeightable))
Run Code Online (Sandbox Code Playgroud)
虽然IList(Of T)是不变的,IEnumerable(Of T)是协变的T,因为API永远只允许类型的值T将返回由它-没有任何类型的参数T中的方法IEnumerable(Of T).所以有转换List(Entity)为IEnumerable(Of IWeightable).
通用方差是一个毛茸茸的话题 - 在NDC 2010上我给出了一个你可能觉得有用的演示文稿.您可以在NDC 2010视频页面上观看.(搜索"差异.")
如果您使用的是.NET 3.5或更早版本,Konrad建议制作Calculate通用版是一个不错的选择.