I need to use only 1 function to process a list containing interface types so that I can reuse it for each subtype, but I also need to know the concrete type when handling the list-items higher up the function call stack:
LoadAItems
calls GetA
which calls FilterItems
.
FilterItems
needs to be generic so that GetB
can also call and make use of it.
The problem is that trying to pass the list of subtypes to the general FilterItems
method is not allowed:
"Cannot convert type 'List(Of AListItem)' to parameter type 'List(Of IListItem)'"
I tried converting each AListItem object in the list to IListItem and adding it to a new list but the problem is that the FilterItems
function is supposed to remove elements from the list. If I remove elements from the new list then it will not affect the old list. I could convert it back but this is a lot of hassle just to be able to use the function.
I cannot just change everything to List(Of IListItem)
because then I would need to always cast down the returned value from either FilterItems
or GetA
/ GetB
because LoadAItems
/ LoadBItems
needs to know the concrete type.
I can see why casting down is bad, but why can't I cast up to the interface type the concrete types are implementing?
I have already tried:
FilterItems(CType(items, List(Of IListItem))
but this is not allowed:
"Value of type 'List(Of AListItem)' cannot be converted to 'List(Of IListItem)'"
Here is my code example:
Public Class AListItem
Implements IListItem
'Properties here
End Class
Public Class BListItem
Implements IListItem
'Properties here
End Class
Private Sub FilterItems(items As List(Of IListItem))
'Remove items from the list that meet some condition
items.RemoveAll(Function(item) ...)
'Does not matter what the items class type is
End Sub
Public Function GetA() As List(Of AListItem)
Dim items As List(Of AListItem)
items = CallDatabase()
FilterItems(items) ' Does not allow!
Return items
End Function
Public Function GetB() As List(Of BListItem)
Dim items As List(Of BListItem)
items = CallDatabase()
FilterItems(items) ' Does not allow!
Return items
End Function
Public Sub LoadAItems()
Dim items As List(Of AListItem)
items = GetA()
'Do specific AListItem stuff (cannot use interface!)
End Sub
Public Sub LoadBItems()
Dim items As List(Of BListItem)
items = GetB()
'Do specific BListItem stuff (cannot use interface!)
End Sub
If I correctly understand what you're trying to do you should be able to make the function itself generic:
Private Sub FilterItems(Of T As IListItem)(items As List(Of T))
Of T As IListItem
adds a constraint that T
must be, or inherit from IListItem
.
Then you can call it like:
Public Function GetA() As List(Of AListItem)
Dim items As List(Of AListItem)
items = CallDatabase()
FilterItems(Of AListItem)(items)
Return items
End Function
Public Function GetB() As List(Of BListItem)
Dim items As List(Of BListItem)
items = CallDatabase()
FilterItems(Of BListItem)(items)
Return items
End Function