如何将类转换为它派生的抽象通用基类?

时间:2014-07-30 17:57:56

标签: vb.net generics inheritance interface covariance

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

通用基类:

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]'“。

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

1 个答案:

答案 0 :(得分:0)

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

在您的情况下,将您的演员表写为

someProperty = instanceOfCollection1.Cast(Of CollectionItemBase)

此演员表会返回您可以使用的IEnumerable(Of CollectionItemBase)

但我不认为这是你的问题。让我们把这一行代码放在一边,谈谈你的问题。事实是仿制药不会那样工作。通用类型的基础/派生类型是完全不同的类型。

在最简单的示例中,A(Of T)的实例即使A(of U)继承自T,也无法转换为U,因为A(Of U)是不同于'A(Of U)..

的类型

用真实的类替换类名:。的实例     Collection1

或者说

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 

希望这很有用