我在VB.net工作并有一个Class,Foo,它实现了一个接口,IBar。我有一个Foo列表,但是我需要将一个IBar列表传递给一个函数,但是即使我使用DirectCast,我仍然会出现转换错误。我的代码是
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
在Main2和Main2中,我得到了
Value of type 'System.Collections.Generic.List(Of FreezePod.Pod.Foo)' cannot be converted to 'System.Collections.Generic.List(Of FreezePod.Pod.IBar)'.
MainWorks可以工作,但是在我想要调用此函数的任何地方都必须这样做是非常烦人和低效的。
答案 0 :(得分:5)
问题是像List(Of T)这样的泛型类型不会转换为其他List(Of U),即使转换被保证是安全的。 VS2010提供了这方面的帮助,当然,这对你没有任何帮助。
正如我认为在链接的线程中也提示,如果DoIt可以使用IEnumerable的IBar而不是列表,你可以这样做:
DoIt(FooList.Cast(Of IBar))
或者如果你真的需要一个列表(并且可以承担管理费用),你可以获得一个列表:
DoIt(FooList.Cast(Of IBar).ToList)
答案 1 :(得分:4)
Duplicate question但是对于C#(同样的问题)。你可以将各种答案翻译成VB。你不能的原因是covariance and contravariance。
我不是VB人,但我首选的C#方式是拨打System.Collections.Generic.List<T>.ConvertAll<Tout>(x => (Tout)x)
。 (我不知道如何将其翻译成VB。)
VB翻译:
System.Collections.Generic.List(Of T).ConvertAll(Of TOut)(Function(x) CType(x, TOut))
答案 2 :(得分:2)
添加此解决方案作为另一个答案,这应该做你想要的。
Sub DoIt(Of T As IBar)(ByVal l As List(Of T))
End Sub
使用泛型定义sub。
答案 3 :(得分:1)
派生的基类不是一个选项,而是让基类实现接口。这将使它发挥作用。
Class BaseFoo
Implements IBar
End Class
Class Foo
Inherits BaseFoo
End Class
Sub DoIt(ByVal l As List(Of BaseFoo))
End Sub
喜欢它。