Using an object from a Generically defined class as a variable.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • BBM

    #1

    Using an object from a Generically defined class as a variable.

    I have the following base class that uses Generics in its definition.

    MyList(of T, C) - T is a BindingList(Of C), C is the type
    in the list

    I have many implemented classes that use this definition...

    Class A ( of A, C)
    Class B(of B,C) and so on.

    Now I want to write a class that has a variable to which ANY of the derived
    classes
    of MyList(of T,C) can be assigned.

    What is the syntax? When I try to tell the system that the type of the
    variable is "MyList" it proceeds assuming that I'm making a derivative class
    and wants me
    to specify what types "T" and "C" are.

    How do I do this?

    Thanks.


  • Larry Lard

    #2
    Re: Using an object from a Generically defined class as a variable.


    BBM wrote:[color=blue]
    > I have the following base class that uses Generics in its definition.
    >
    > MyList(of T, C) - T is a BindingList(Of C), C is the type
    > in the list
    >
    > I have many implemented classes that use this definition...
    >
    > Class A ( of A, C)
    > Class B(of B,C) and so on.
    >
    > Now I want to write a class that has a variable to which ANY of the derived
    > classes
    > of MyList(of T,C) can be assigned.
    >
    > What is the syntax?[/color]

    This doesn't work the way you want. To use an example from the
    framework - consider List(Of T). You want to be able to write

    Class Foo
    Private L As ...

    where Foo.L can be assigned any particular List(Of something), so we
    could assign to Foo.L a List(Of String), a List(Of Integer), and so on.
    But remember that generics are all about providing compile-time type
    safety: so what could we possibly do with Foo.L? We couldn't say
    L.Add(x), because the compiler wouldn't be able to verify that x was
    typesafe to be added to this particular List(Of something). We couldn't
    pull an item out of L, because the compiler wouldn't know what type it
    was.

    The principle here is that the constructed classes are *not* 'derived'
    from a generic 'base class' - this is a different mechanism from
    inheritance. There _is_ no base class.

    So what can we do? There are two things:

    1) If we want to just pass instances of the constructed classes around,
    knowing that we can't type-safely dig into them, we can define an
    interface that exposes that behavior we will want at runtime, and have
    the generic class implement this interface. For example, List(Of T)
    implements IList, so a List(Of String) and a List(Of Integer) could
    both be assigned to

    Private L As IList

    Note that all we can say about L is that it contains Objects: we cannot
    safely add items to it, nor assume the type of objects we pull out of
    it.

    So in your case you would define

    Interface IMyList

    then have MyList(Of T,C) implement this interface. Bear in mind that
    IMyList is not generic, and can't expose generic types (so you can't
    have IMyList.Add(ite m As C), for example).

    2) If you are going to have a class that contains a member with a
    generic type, and you want type-safe access to this member, then the
    containing class needs to be a generic type itself, with appropriate
    constraints.

    So you already have

    Class MyList(Of T As BindingList(Of C), C)

    and you want a type that contains a MyList, so you would say:

    Class ContainsList(Of T As BindingList(Of C), C)

    Private list As MyList(Of T, C)

    End Class

    This of course means that ContainsList is 'tied' by type to the
    particular MyList it contains - your message suggests you might want to
    arbitrarily associate different MyList's to any ContainsList, in which
    case the interface option is better - but you lose compile-time type
    safety.

    --
    Larry Lard
    Replies to group please

    Comment

    • BBM

      #3
      Re: Using an object from a Generically defined class as a variable

      Thanks for the detailed explanation. I had stumbled upon the second approach
      myself (the "ContainsLi st" approach), but I was having trouble working
      through the syntax. My actual situation is slightly more complex than your
      example, but I was able to use your code as a template and get mine to work.

      Thanks for your help!

      BBM

      "Larry Lard" wrote:
      [color=blue]
      >
      > BBM wrote:[color=green]
      > > I have the following base class that uses Generics in its definition.
      > >
      > > MyList(of T, C) - T is a BindingList(Of C), C is the type
      > > in the list
      > >
      > > I have many implemented classes that use this definition...
      > >
      > > Class A ( of A, C)
      > > Class B(of B,C) and so on.
      > >
      > > Now I want to write a class that has a variable to which ANY of the derived
      > > classes
      > > of MyList(of T,C) can be assigned.
      > >
      > > What is the syntax?[/color]
      >
      > This doesn't work the way you want. To use an example from the
      > framework - consider List(Of T). You want to be able to write
      >
      > Class Foo
      > Private L As ...
      >
      > where Foo.L can be assigned any particular List(Of something), so we
      > could assign to Foo.L a List(Of String), a List(Of Integer), and so on.
      > But remember that generics are all about providing compile-time type
      > safety: so what could we possibly do with Foo.L? We couldn't say
      > L.Add(x), because the compiler wouldn't be able to verify that x was
      > typesafe to be added to this particular List(Of something). We couldn't
      > pull an item out of L, because the compiler wouldn't know what type it
      > was.
      >
      > The principle here is that the constructed classes are *not* 'derived'
      > from a generic 'base class' - this is a different mechanism from
      > inheritance. There _is_ no base class.
      >
      > So what can we do? There are two things:
      >
      > 1) If we want to just pass instances of the constructed classes around,
      > knowing that we can't type-safely dig into them, we can define an
      > interface that exposes that behavior we will want at runtime, and have
      > the generic class implement this interface. For example, List(Of T)
      > implements IList, so a List(Of String) and a List(Of Integer) could
      > both be assigned to
      >
      > Private L As IList
      >
      > Note that all we can say about L is that it contains Objects: we cannot
      > safely add items to it, nor assume the type of objects we pull out of
      > it.
      >
      > So in your case you would define
      >
      > Interface IMyList
      >
      > then have MyList(Of T,C) implement this interface. Bear in mind that
      > IMyList is not generic, and can't expose generic types (so you can't
      > have IMyList.Add(ite m As C), for example).
      >
      > 2) If you are going to have a class that contains a member with a
      > generic type, and you want type-safe access to this member, then the
      > containing class needs to be a generic type itself, with appropriate
      > constraints.
      >
      > So you already have
      >
      > Class MyList(Of T As BindingList(Of C), C)
      >
      > and you want a type that contains a MyList, so you would say:
      >
      > Class ContainsList(Of T As BindingList(Of C), C)
      >
      > Private list As MyList(Of T, C)
      >
      > End Class
      >
      > This of course means that ContainsList is 'tied' by type to the
      > particular MyList it contains - your message suggests you might want to
      > arbitrarily associate different MyList's to any ContainsList, in which
      > case the interface option is better - but you lose compile-time type
      > safety.
      >
      > --
      > Larry Lard
      > Replies to group please
      >
      >[/color]

      Comment

      Working...