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.
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)
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))
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With