【问题标题】:Confusion - implemented Interface needs casting?困惑 - 实现的接口需要强制转换?
【发布时间】:2011-06-07 20:16:37
【问题描述】:

我有一个实现 IWeightable 的实体类:

Public Interface IWeightable

    Property WeightState As WeightState

End Interface

我有一个 WeightCalculator 类:

Public Class WeightsCalculator

    Public Sub New(...)
        ...
    End Sub

    Public Sub Calculate(ByVal entites As IList(Of IWeightable))
        ...
    End Sub

End Class

按照流程:

  1. 实例化实体集合 Dim entites As New List(Of Entity)
  2. 实例化权重计算器Dim wc As New WeightsCalculator(...)

为什么我不能做 wc.Calculate(entities)?我收到:

无法转换类型的对象 'System.Collections.Generic.List1[mynameSpace.Entity]' to type 'System.Collections.Generic.IList1[myNamespace.IWeightable]'。

如果实体实现了 IWeightable 为什么这不可能?

【问题讨论】:

    标签: .net vb.net collections interface


    【解决方案1】:

    这不起作用。

    假设您有一个不同的类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())
    

    这是非法的。如果不是,entities(0) 的内容会是什么?

    要使代码正常工作,请改用带有约束的泛型方法:

    Public Sub Calculate(Of T As IWeightable)(ByVal entites As IList(Of T))
        ...
    End Sub
    

    【讨论】:

    • 啊,我知道我很天真。我将实现泛型方法。
    【解决方案2】:

    List(Of Entity) 不是IList(Of IWeightable)。考虑这段代码(OtherWeightable 实现 IWeightable):

    Dim list As IList(Of IWeightable) = New List(Of Entity)
    list.Add(new OtherWeightable)
    

    关于编译的第二行 - 没有任何可疑之处 - 但您不希望 List(Of Entity) 中包含 OtherWeightable 元素。

    .NET 4 以 通用方差 的形式对此有一个部分解决方案。如果您的 Calculate 方法仅迭代 entities,您可以将签名更改为:

    Public Sub Calculate(ByVal entites As IEnumerable(Of IWeightable))
    

    虽然IList(Of T)不变IEnumerable(Of T)T 中是协变,因为API 只允许T 类型的值是由它返回 - 在IEnumerable(Of T) 的方法中没有T 类型的参数。所以有一个从List(Entity)IEnumerable(Of IWeightable) 的转换。

    泛型方差是一个棘手的话题 - 在 NDC 2010 上,我做了一个演示,您可能会发现它很有用。您可以在NDC 2010 videos page 观看。 (搜索“差异”。)

    如果您使用的是 .NET 3.5 或更早版本,Konrad 建议将 Calculate 设为泛型是一个不错的选择。

    【讨论】:

    • 感谢您在回复上花费的时间 - 这是一个很大的帮助。
    猜你喜欢
    • 1970-01-01
    • 2013-05-22
    • 2011-01-18
    • 1970-01-01
    • 2015-04-11
    • 2021-06-23
    • 2012-04-10
    • 1970-01-01
    相关资源
    最近更新 更多