开发者

VB.Net Inheritance and Interfaces

Has someone a hint what I'm doing wrong in VB.Net?

Module Module1

Interface ISearch(Of T As ISearchResult)
    Function ids() As List(Of T)
End Interface

Interface ISearchResult
    Function id() As String
End Interface

MustInherit Class BasicSearch(Of T As ISearchResult)
    Implements ISearch(Of T)

    MustOverride Function ids() As System.Collections.Generic.List(Of T) Implements ISearch(Of T).ids

End Class

Class Search
    Inherits BasicSearch(Of SearchResult)
    Implements ISearch(Of SearchResult)


    Overrides Function ids() As System.Collections.Generic.List(Of Searc开发者_C百科hResult)
        Return New List(Of SearchResult)
    End Function
End Class

Class SearchResult
    Implements ISearchResult
    Public Function id() As String Implements ISearchResult.id
        Return "id"
    End Function
End Class

Sub Main()

    Dim foo As New Search()
    Dim bar As Object = foo
    Dim foobar As ISearch(Of ISearchResult) = foo

End Sub

End Module

The third cast isn't working. Why?

did I miss a oop lesson?

thanks


An ISearch(Of SearchResult) isn't an ISearch(Of ISearchResult) - they have different generic type parameters. Search is an ISearch(Of SearchResult).


Brian's answer covers the covariance, etc, stuff for .NET 4 that I'd planned to add to this question later (I wrote the initial answer quickly and then had to go offline - by the time I got back, Brian had answered)


To answer mr. moes comment - Imagine if ISearch had another method:

Sub AddID(ID as T)

and assuming we then implement that in Search (which, remember, is ISearch(Of SearchResult), so T is SearchResult). And assume we had something else that implements ISearchResult, say:

Public Class BadNews
    Implements ISearchResult

    Public Function id() As String Implements ISearchResult.id
        Return "other"
    Function
End Class

Now, if your cast worked, we could now call:

foobar.AddID(New BadNews)

But this can't work - the implementation of AddID that we're calling is the one implemented by Search - and that function is only expecting to receive objects of type SearchResult.


The cast does not work because foobar is a ISearch(Of ISearchResult) and foo is a ISearch(Of SearchResult which are not compatible and no implicit conversion operator exists.

.NET 4.0 introduced the concept of covariant and contravariant generic type parameters which can be used to solve this problem elegantly. If you tried to compile the code with VB 10 you would get this error.

error BC36757: 'Module1.Search' cannot be converted to 'Module1.ISearch(Of Module1.ISearchResult)'. Consider changing the 'T' in the definition of 'Interface ISearch(Of T As Module1.ISearchResult)' to an Out type parameter, 'Out T'.

Following the recommendation you can indicate that T is covariant in ISearchResult by using the new Out keyword.

Interface ISearch(Of Out T As ISearchResult)
    Function ids() As List(Of T)
End Interface

Unfortunately we now get this error.

error BC36724: Type 'T' cannot be used in this context because 'T' is an 'Out' type parameter.

The reason is because List(Of T) is not covariant itself. However, IEnumerable(Of T) is. So this would be okay.

Interface ISearch(Of Out T As ISearchResult)
    Function ids() As IEnumerable(Of T)
End Interface

You would then need to make the same change from List(Of T) to IEnumerable(Of T) for the other declarations as well.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜