Nicholas
Nicholas

Reputation: 35

Passing List (Of ChildClass) as parameter to method expecting List (Of ParentClass)?

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

Answers (2)

monty
monty

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

Jon Skeet
Jon Skeet

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

Related Questions