假设我有这个Sub:
Sub Process(InputQueue as ConcurrentQueue(Of Object))
.... some codes ....
End Sub
现在我有了这个
Class JobDesc
.... some codes ....
End Class
Dim MainJobQueue As New ConcurrentQueue(Of JobDesc)
如果我尝试将MainJobQueue
作为参数传递给Process()
,为什么VB.Net会抱怨?
即,这样做:
Process(MainJobQueue)
将导致以下错误消息:
'ConcurrentQueue(Of JobDesc)'类型的值无法转换为'ConcurrentQueue(Of Object)'。
JobDesc
不是Object
的子类,因此将JobDesc
投射到Object
会是'扩大'而不是缩小?
答案 0 :(得分:2)
您可以创建这样的通用方法(即如果我仍然记得vb.net)
Sub Process(of T as Object)(InputQueue as ConcurrentQueue(Of T))
答案 1 :(得分:1)
JobDesc不是Object的子类,因此将JobDesc转换为Object将是一个扩展'而不是缩小?
是的,但问题是ConcurrentQueue
是可变集合。
因此,它的类型参数不仅定义了可以从中获取的对象,还定义了它将接受的 new 元素。
如果您可以直接将其投射到ConcurrentQueue(of Object)
,则可以执行此操作:
Sub Process(InputQueue as ConcurrentQueue(Of Object))
InputQueue.Enqueue("Whoops, this is not a JobDesc!")
End Sub
Process(MainQueue)
Dim getLatestJob = MainQueue.Dequeue() // WTF, why did it give me a String?
(好吧,理论上。如果你真的设法编译了这个,那么程序会因InvalidCastException
而崩溃。)
现在,如果您不计划将任何非JobDesc
元素添加到队列中,那么您有几个选项。
您可以通过将Process
编写为通用方法来强制执行类型约束。
Sub Process(Of SomeType)(InputQueue as ConcurrentQueue(Of SomeType))
InputQueue.Enqueue("Whoops, this is not a SomeType!")
// will not compile, input is not SomeType
End Sub
或者,您可以将ConcurrentQueue
转换为基类或类似IEnumerable(Of T)
的接口,不允许向集合添加新元素,因此可以安全地转换为更广泛的类型,如Object
(技术术语:covariant
)。
Dim MainQueueReadOnly As IEnumerable(Of JobDesc) = MainQueue
Sub Process(InputQueue as IEnumerable(Of Object))
InputQueue.Enqueue(anything)
// will not compile as IEnumerable doesn't have an .Enqueue method
End Sub
但是,如果您 ,打算在队列中添加一些Object
,那么您唯一的选择就是创建一个新的,不同的集合InputQueue
,将接受除JobDesc
以外的其他类型的元素。
Dim newQueue As New ConcurrentQueue(Of Object)(MainJobQueue)
答案 2 :(得分:0)
这并不像您期望的那样工作,因为IEnumerable<Base>
不是协变的。来自CreateModelMixin:
协方差可让您使用比最初指定更多的派生类型。
您可以将IEnumerable(IEnumerable(Of Derived)在Visual Basic中)的实例分配给类型为
IEnumerable(Of Object)
的变量。
如果您将方法更改为接受IReadOnlyList(Of Object)
或Sub Process(InputQueue As IEnumerable(Of Object))
'....some codes ....
End Sub
,那么它的编译就可以了,因为这些接口是协变的:
requirements:
Django==1.8.8
kombu==3.0.35
celery==3.1.23
django-celery==3.1.17