Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I cast a list of an object to a list of an interface that the object implements in VB.net?

Tags:

.net

vb.net

I am working in VB.net and have a Class, Foo, that implements an interface, IBar. I have a List of Foo's, but I need to pass a list of IBar's into a function, but I keep getting casting errors, even when I use DirectCast. My code is

Class Foo
    Implements IBar
End Class

Interface IBar
End Interface

Sub DoIt(ByVal l As List(Of IBar))
End Sub

Sub Main()
    Dim FooList As New List(Of Foo)
    DoIt(FooList)
End Sub

Sub Main2()
    Dim FooList As New List(Of Foo)
    DoIt(DirectCast(FooList, List(Of IBar)))
End Sub

Sub MainWorks()
    Dim FooList As New List(Of Foo)
    Dim IBarList As New List(Of IBar)

    For Each f As Foo In FooList
        IBarList.Add(f)
    Next

    DoIt(DirectCast(IBarList, List(Of IBar)))
    DoIt(IBarList)
End Sub

In both Main and Main2 I get

Value of type 'System.Collections.Generic.List(Of FreezePod.Pod.Foo)' cannot be converted to 'System.Collections.Generic.List(Of FreezePod.Pod.IBar)'.

MainWorks works, but it would be really annoying and inefficient to have to do that everywhere I want to call this function.

like image 348
thefroatgt Avatar asked May 19 '09 22:05

thefroatgt


3 Answers

The problem is that generic types like List(Of T) don't convert to some other List(Of U) even if the cast is guaranteed to be safe. Help is coming for this in VS2010, which doesn't really help you now, of course.

As I think was also suggested in the thread linked to, if DoIt can take an IEnumerable of IBar instead of a list, you could do:

DoIt(FooList.Cast(Of IBar))

or if you really needed a list (and could take the overhead), you could get a list:

DoIt(FooList.Cast(Of IBar).ToList)
like image 142
panopticoncentral Avatar answered Nov 16 '22 21:11

panopticoncentral


Duplicate question but for C# (same problem). There are various answers there you can translate to VB. The reason why you can't is covariance and contravariance.

I'm not a VB guy but my preferred C# way is to call System.Collections.Generic.List<T>.ConvertAll<Tout>(x => (Tout)x). (I don't know how that translates, if it does, to VB.)

VB translation:

System.Collections.Generic.List(Of T).ConvertAll(Of TOut)(Function(x) CType(x, TOut))

like image 34
Colin Burnett Avatar answered Nov 16 '22 20:11

Colin Burnett


Is a derived Base Class not an option, and have the Base Class implement the interface. That would make it work.

Class BaseFoo
    Implements IBar
End Class

Class Foo
    Inherits BaseFoo
End Class

Sub DoIt(ByVal l As List(Of BaseFoo))
End Sub

Something like it.

like image 33
AnotherDan Avatar answered Nov 16 '22 21:11

AnotherDan