【问题标题】:How does one go about converting a class to an abstract generic base class from which it derives?如何将一个类转换为派生它的抽象泛型基类?
【发布时间】:2014-09-22 12:03:41
【问题描述】:

我目前在 Visual Studio 2013 中使用 .NET 4.5 上的 VB。我有一个抽象基类,它包含另一个抽象基类的集合,如下所示:

通用基类:

Public MustInherit Class CustomCollection(Of collectionItemType As CollectionItemBase)
    Inherits Collections.ObjectModel.KeyedCollection(Of String, CollectionItemBase)
    '...
End Class

通用基类引用的基类:

Public MustInherit Class CollectionItemBase
    '...
End Class

我有一组继承通用基类“CustomCollection”的类:

Public Class Collection1
    Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
    '...
End Class

Public Class Collection2
    Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase2)
    '...
End Class

'etc...

这是我用来尝试将 Collection1 的实例转换为 CustomCollection(Of CollectionItemBase) 的代码:

'...
someProperty = instanceOfCollection1.Cast(Of CustomCollection(Of CollectionItemBase))
'...

这会在运行时产生以下错误,对我来说这似乎是无稽之谈:

“无法转换类型的对象 'd__b1`1[ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]]' 输入 'ApplicationName.CustomCollection`1[ApplicationName.CollectionItemBase]'。”

它似乎声称它无法将对象转换为自己的类型。有什么想法吗?

【问题讨论】:

  • 这段代码有问题。 Inherits CustomCollection(Of ClassThatDerivesFromCustomCollection1) 不应该是 Inherits CustomCollection(Of ClassThatDerivesFromCollectionItemBase1) 吗?
  • @Alireza 是的,你是对的!抱歉,我在翻译代码时犯了一个错误,我会立即修复。但是,这在原始代码中不是问题。如果您知道可能导致潜在问题的原因,请告诉我! :-)
  • 哦,不。我想澄清一下,然后发布我的答案。我已经准备好了答案:)
  • @Alireza 太棒了,迫不及待地想阅读它!试图弄清楚这一点是一场噩梦。

标签: vb.net generics inheritance interface covariance


【解决方案1】:

当您在IEnumerable(Of U) 上使用Cast(Of T) 时,它会将每个单独的元素转换为目标类型,因此您不应传递IEnumerable(Of T) 的类型,而应传递T 本身。

在你的情况下,将你的演员写成

someProperty = instanceOfCollection1.Cast(Of CollectionItemBase)

此转换返回您可以使用的IEnumerable(Of CollectionItemBase)

但我认为这不是你的问题。让我们把那一行代码放在一边,谈谈你的问题。事实是泛型不是那样工作的。 Base/Derived 类型的泛型类型是完全不同的类型。

在最简单的示例中,即使 T 继承自 UA(Of T) 的实例也不能转换为 A(of U),因为 A(Of U) 的类型与 `A(Of U) 不同。 .

用你的真实类替换类名: 收藏1

或者说

CustomCollection(Of ClassThatDerivesFromCollectionItemBase1)

不能转换成

CustomCollection(Of CollectionItemBase) 

尽管

ClassThatDerivesFromCollectionItemBase1 
    Inherits CollectionItemBase

因为

CustomCollection(Of ClassThatDerivesFromCollectionItemBase1) 

是不同的类型
CustomCollection(Of CollectionItemBase).

这与协方差无关,因为(来自MSDN):

在 .NET Framework 4 中,变体类型参数仅限于 泛型接口和泛型委托类型。

所以它对敌人类不起作用,但对接口起作用。让我对您的代码进行一些更改:

Public Class CollectionItemBase
End Class

Public Class ClassThatDerivesFromCollectionItemBase1
    Inherits CollectionItemBase
End Class

Public Class ClassThatDerivesFromCollectionItemBase2
    Inherits CollectionItemBase
End Class

Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)
End Interface

Public Class Collection1
    Implements ICustomCollection(Of ClassThatDerivesFromCollectionItemBase1)
End Class

此行中的Out 修饰符

Public Interface ICustomCollection(Of Out collectionItemType As CollectionItemBase)

使类型参数协变,这意味着如果你有

Dim instanceOfCollection1 As New Collection1

这两行将起作用:

Dim x As ICustomCollection(Of CollectionItemBase) = instanceOfCollection1 
Dim y As ICustomCollection(Of Item1) = instanceOfCollection1 

希望对你有帮助

【讨论】:

  • 非常感谢!因为在我的应用程序中有相当多的类需要根据从抽象类到接口的 CustomCollection 转换进行更新,所以稍后我会回复您的结果!再次,我非常感谢您的努力,并在阅读您的回复后感到乐观,我可能最终能够一起修补解决方案:-)
  • 所以我现在正在将 CustomCollection 转换为接口,但是我很难找到一种有效的方法来保证任何实现 ICustomCollection 的类也将作为 KeyedCollection 的与 ICustomCollection 的指定 CollecitonItemBase 类型相同类型的项目。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2014-02-19
  • 2015-02-13
  • 2012-10-31
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多