Link to home
Start Free TrialLog in
Avatar of apuma
apumaFlag for United States of America

asked on

How to Pass Custom Interface Lists

Hello Experts,

I am trying to pass a list of custom items to a form and having some issues

this is the form cunstructor
Public Class frmSelectDisplayColumns
    Public Sub New(ByVal DCs As List(Of CacheDisplayColumn))
'...
    End Sub
end class

'The Base Class of my Objects
<System.Serializable()> Partial Public MustInherit Class CacheDisplayColumn
End Class

'The Super classes of my Object
<System.Serializable()> Public Class PriceDisplayColumn
    Inherits CacheDisplayColumn
end class

<System.Serializable()> Public Class ItemDisplayColumn
    Inherits CacheDisplayColumn
end class

'and the calling code
 Private myIDCs As New List(Of ItemDisplayColumn)
Public Sub Choose_Columns()
        Dim f As New frmSelectDisplayColumns(Me.myIDCs)
        f.ShowDialog()
    End Sub

Open in new window


This throws an error on the line ;  Dim f As New frmSelectDisplayColumns(Me.myIDCs)
Value of type 'System.Collections.Generic.List(Of ...ItemDisplayColumn)' cannot be converted to 'System.Collections.Generic.List(Of ...CacheDisplayColumn)

I also tried making an Interface for and implementing it in the base class "cachedisplaycolumn" and changing the form constructor to accept a list of that interface and received the same conversion error [except for the interface instead of the base class)

I believe i could ask for a list of Object and then recast in the form constructor.
of create a base class list before calling the form constructor but those both seem dirty and i thought one of the points to interfaces and base classes was for situations like this.

so i think i am missing something here. and i am hoping you experts can shine some light for me.

Thanks,
anthony


Avatar of Jacques Bourgeois (James Burger)
Jacques Bourgeois (James Burger)
Flag of Canada image

I might be wrong, but here is how I see the situation.

As all the generic classes, the List class does not exist as such. List is a template that is used to build a new class into your application when you compile it.

So List(Of CacheDisplayColumn) and List(Of ItemDisplayColumn) are 2 completely individual classes. Since List(Of ItemDisplayColumn) does not inherit from List(Of CacheDisplayColumn), you cannot pass the first one in the second.

At first sight, I do not see how the problem could be solved through generic classes. You might be able to create something such as A class that is a list of your base class...
<System.Serializable()> Partial Public MustInherit Class ListOfCacheDisplayColumn
    Inherits List(Of CacheDisplayColumn))
End Class

Open in new window

... and inherits from that one to create lists for the other classes:
<System.Serializable()> Public Class ListOfItemDisplayColumn
    Inherits ListOfCacheDisplayColumn
end class

<System.Serializable()> Public Class ListOfPriceDisplayColumn
    Inherits ListOfCacheDisplayColumn
end class

Open in new window

Since there is direct inheritance between those, you could pass the ListOfItemDisplayColumn or the ListOfPriceDisplayColumn to a constructor that expects a ListOfCacheDisplayColumn.

Not sure it would work.

You might end up having to resort to the old ArrayList or inherit from CollectionBase, and work with Object variables for that type of thing.




Avatar of apuma

ASKER

Thanks James, I think if i went through the trouble of making the generic list classes i might find myself with the same issue just in a different place in code

This article appears to be explaining why .Net cannot make these types of conversions
http://stackoverflow.com/questions/2346763/any-simple-way-to-explain-why-i-cannot-do-listanimal-animals-new-arraylistdo


and so i believe i will be forced to create a List(of CacheDisplayColumn) and fill it with the ItemDisplaycolumns in the calling code,  then pass that list to the form constructor

I will try that and post my results
ASKER CERTIFIED SOLUTION
Avatar of apuma
apuma
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
One idea that comes to mind.

Your Form could have different constructors, one for each type of list. A simple loop would enable you to transfer it to the base list. Unless you have a very large number of objects, this would be very fast since the individual objects are handled as pointers.
Public Class frmSelectDisplayColumns

    Private ListOfCacheDisplayColumn List(Of CacheDisplayColumn)

    Public Sub New(ByVal DCs AsList(Of ItemDisplayColumn))
        For Each column as ItemDisplayColumn in DCs
            ListOfCacheDisplayColumn.Add(column)
        Next
    End Sub

    Public Sub New(ByVal DCs AsList(Of PriceDisplayColumn))
      For Each column as PriceDisplayColumn in DCs
            ListOfCacheDisplayColumn.Add(column)
        Next
    End Sub

End Class

Open in new window

Avatar of apuma

ASKER

Private myIDCs As New List(Of ItemDisplayColumn)
Public Sub Choose_Columns()
        Dim CDCs As New List(Of CacheDisplayColumn)
        CDCs.AddRange(Me.IDCs.ToArray)
        Dim f As New frmSelectDisplayColumns(CDCs)
End Sub

Open in new window


as stated in the original question i had to  create a base class list before calling the form constructor
Avatar of apuma

ASKER

I think we are on the same page, but it seems easier to do the conversion when calling the form as apposed to complicating the form's constructor(s).

Avatar of apuma

ASKER

The problem has to do with the covariance and contravariance as outlined in linked articles