泛型,接口和转换问题

jba*_*bey 6 vb.net generics user-controls interface

我最近为我实现的一些自定义用户控件添加了一个界面.界面非常基础.它有一种支持链接的方法:

Public Interface IMyInterface(Of T As WebControl)
    Function DoSomething() As T
End Interface
Run Code Online (Sandbox Code Playgroud)

实现也很基本:

Public Class MyCustomControl
    Inherits CompositeControl
    Implements IMyInterface(Of MyCustomControl)

Public Function DoSomething() As MyCustomControl _
    Implements IMyInterface(Of MyCustomControl).DoSomething
    ' do stuff

    Return Me
End Class
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切正常.当我尝试遍历所有实现IMyInterface接口的控件集合时会出现问题,如下所示:

Dim myList = New List(Of IMyInterface(Of WebControl))

myList.Add(someCustomControl)

myList.ForEach(Sub(i) i.DoSomething())
Run Code Online (Sandbox Code Playgroud)

someCustomControl是一个MyCustomControl实现IMyInterface(Of MyCustomControl)而不是IMyInterface(Of WebControl).

我在第二行(我尝试添加someCustomControl)中收到此错误:

Option Strict On禁止从"MyCustomControl"到"IMyInterface(Of WebControl)"的隐式转换.

有没有办法解决这个错误?我很接近它的工作,但我不太了解泛型超越这一点.

chu*_*e x 4

协方差是 VS 2010 中引入的一项语言功能,可以解决您的问题。您需要定义泛型,使类型前面T有关键字:Out

Public Interface IMyInterface(Of Out T As WebControl)
    Function DoSomething() As T
End Interface

当您使用Out关键字时,您正在使用协方差。它允许使用更派生类型的泛型来代替具有基类型的泛型。因此,在您的情况下,它将允许IMyInterface(Of MyCustomControl))在代码通常期望的地方使用对象IMyInterface(Of WebControl)),例如您的for循环。

请注意,协方差有一个限制。协变类型T只能用作函数返回值,而不能用作函数(或子函数)的参数。例如,如果DoSomething签名IMyInterface看起来像这样,编译器会抱怨:

' Here the type T is used as an input param - compiler error
Sub DoSomething(ByVal sampleArg As T)
Run Code Online (Sandbox Code Playgroud)

考虑到您的链接场景,我认为上述限制不是问题。

更多信息请参见 MSDN: