Reputation: 35
I have implemented inheritance for two parent classes called Table and Field. Each parent class has several child classes. In the Table parent class, I created a method that expects parameter List(Of Field).
I get an error when trying to pass in parameter List(Of ChildField) to the method that expects a parameter of List(Of Field). The error message is as below:
Value of type 'System.Collections.Generic.List(Of com.hlb.icisbatch.data.ChildField)'
cannot be converted to 'System.Collections.Generic.List(Of com.hlb.icisbatch.data.Field)'
My question, is it possible to pass in list of child class as parameter? If it is not a list then it works fine. But somehow it is not possible with lists?
Below is sample class structure:
Table Field
| |
ChildTable ChildField
I have a method in the parent class:
Public Class Table
Public Sub New()
End Sub
Public Overridable Sub setFields(ByVal list As List(Of Field)
'Do work here'
End Sub
End Class
and method in child class:
Public Class ChildTable
Public Sub New(ByVal list As List(Of ChildField)
setFields(ChildField)
End Sub
End Class
Upvotes: 1
Views: 4673
Reputation: 1590
So, for .Net 4.0+ (possibly earlier versions too) you'd have to alter your setFields method:
Public Overridable Sub setFields(As T Of Field)(ByVal list As List(Of T)
'Do work here'
End Sub
Then when you call it with:
Public Sub New(ByVal list As List(Of ChildField)
setFields(list)
End Sub
it is essentially calling:
setFields(Of ChildField)(list)
which means that the setFields knows it is dealing with a list of ChildField objects and won't let anyone do anything naughty like add a different ChildNumber2Field object.
Although generics were introduced in .Net 2.0, I'm not sure exactly how advanced that version was wrt doing this kind of thing.
Upvotes: 0
Reputation: 1502206
No, this isn't possible - and for good reason. Consider what would happen if the calling code tried to add an instance of Field
(or some other derived class) to the list. Bad stuff would happen.
In .NET 4 (and presumably VB10) this is possible via covariance and contravariance of generic delegates and interfaces (not classes) - but only where it's safe. So IList(Of T)
is not variant (because values go "in" and "out" of the API); IEnumerable(Of T)
is covariant (so there's a conversion from IEnumerable(Of String)
to IEnumerable(Of Object)
) and IComparer(Of T)
is contravariant (so there's a conversion from IComparer(Of Object)
to IComparer(Of String)
for example).
(This ability has actually been in the CLR since v2.0, but it's only surfaced in the languages and framework for .NET 4.)
Upvotes: 1