List(Of clsClass) = List(Of clsSubClass)

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

    List(Of clsClass) = List(Of clsSubClass)

    Hi,

    I have a class clsSubClass which inherits from clsClass.

    When I instantiate an object of clsClass (MyClass), and I instantiate an
    object from clsSubclass (MySubClass) I can do an "MyClass = MySubclass".

    But when I declare two generic list of them ("Dim MyList1 as List(Of
    clsClass)" and "Dim MyList2 as List(Of clsSubClass)"), I can't do an
    "MyList1 = MyList2".

    Why is this exactly, and is there a way to implement this behaviour?


    Thanks a lot in advance,


    Pieter


  • Paul E Collins

    #2
    Re: List(Of clsClass) = List(Of clsSubClass)

    "Pieter" <pieterNOSPAMco ucke@hotmail.co mwrote:
    When I instantiate an object of clsClass (MyClass), and I instantiate an
    object from clsSubclass (MySubClass) I can do an "MyClass = MySubclass".
    But when I declare two generic list of them ("Dim MyList1 as List(Of
    clsClass)" and "Dim MyList2 as List(Of clsSubClass)"), I can't do an
    "MyList1 = MyList2".
    Why is this exactly, and is there a way to implement this behaviour?
    You can't do that because it would allow you to add superclass instances to
    a list that, by its definition, is only supposed to contain subclass
    instances.

    Of course, you can write a loop to copy the elements to a separate list of
    another type.

    Eq.


    Comment

    • Jon Skeet [C# MVP]

      #3
      Re: List(Of clsClass) = List(Of clsSubClass)

      On Jul 15, 9:34 am, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:
      I have a class clsSubClass which inherits from clsClass.
      >
      When I instantiate an object of clsClass (MyClass), and I instantiate an
      object from clsSubclass (MySubClass) I can do an "MyClass = MySubclass"..
      >
      But when I declare two generic list of them ("Dim MyList1 as List(Of
      clsClass)" and "Dim MyList2 as List(Of clsSubClass)"), I can't do an
      "MyList1 = MyList2".
      Indeed. That's because generics don't exhibit variance.
      Why is this exactly, and is there a way to implement this behaviour?
      Brief answer: consider this code.
      List<Bananabana naBunch = new List<Banana>();
      List<Fruitfruit bowl = bananaBunch;
      fruitbowl.Add(n ew Apple());

      Suppose this were legal - then bananaBunch would contain an Apple,
      which is clearly invalid.

      For a lot of detail, see Eric Lippert's series of blog articles:


      Jon

      Comment

      • Pieter

        #4
        Re: List(Of clsClass) = List(Of clsSubClass)

        Oh yes indeed you're right :-S I should have thought about that :-)

        Although: An Import doesn't work neither, which should work in my opnion?
        Because clsSubClass is also an clsClass: it shoudl be able to import these
        items...


        "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
        news:e668d643-aa73-459a-b32c-b0f13f6a0b42@l6 4g2000hse.googl egroups.com...
        On Jul 15, 9:34 am, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:


        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: List(Of clsClass) = List(Of clsSubClass)

          On Jul 15, 9:55 am, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:
          Oh yes indeed you're right :-S I should have thought about that :-)
          >
          Although: An Import doesn't work neither, which should work in my opnion?
          Because clsSubClass is also an clsClass: it shoudl be able to import these
          items...
          What exactly would you expect an import to do? You just can't treat a
          list of bananas as if it's a general list of fruit. You can create a
          new list of fruit and copy the contents of a list of bananas into it,
          of course.

          Jon

          Comment

          • Marc Gravell

            #6
            Re: List(Of clsClass) = List(Of clsSubClass)

            Well, what are you meaning by "import"? Any example code?

            One good trick here is to use a generic method; I'll use C# syntax for
            [my] familiarity:

            public void DoSomething<T>( List<Tlist) where T : clsClass
            {

            }

            you can now pass a List<clsClassor a List<clsSubClas s>, but you
            ideally want to talk about "T" inside the method. You are saying "I
            have a list of [something], where that [something] is, or is derived
            from, clsClass".

            Marc

            Comment

            • Pavel Minaev

              #7
              Re: List(Of clsClass) = List(Of clsSubClass)

              On Jul 15, 12:34 pm, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:
              Hi,
              >
              I have a class clsSubClass which inherits from clsClass.
              >
              When I instantiate an object of clsClass (MyClass), and I instantiate an
              object from clsSubclass (MySubClass) I can do an "MyClass = MySubclass"..
              >
              But when I declare two generic list of them ("Dim MyList1 as List(Of
              clsClass)" and "Dim MyList2 as List(Of clsSubClass)"), I can't do an
              "MyList1 = MyList2".
              >
              Why is this exactly, and is there a way to implement this behaviour?
              It has already been explained why it doesn't work like that, but there
              are workarounds, depending on what exactly you're trying to do.
              Typically, you don't want variance on variables - you want it on
              function arguments. In this case, you can use generics yourself. For
              example, say, you have a function that should take an arbitrary
              IEnumerable(Of BaseClass). You could write it like that:

              Public Sub PrintAll(items As IEnumerable(Of BaseClass)
              For Each item In items ...
              End Sub

              But then you won't be able to pass IEnumerable(Of DerivedClass) to
              this function. The workaround is to do this:

              Public Sub PrintAll(Of TItem As BaseClass)(item s As IEnumerable(Of
              TItem))
              For Each item In Items ...
              End Sub

              Now that the function is explicitly declared as taking IEnumerable of
              _any_ TItem which inherits from BaseClass, it can take IEnumerable(Of
              DerivedClass) just fine.

              Unfortunately, this workaround is for covariance only; you cannot do
              usage-site contravariance with it (e.g. write a method that works on
              any IList(Of TItem) such that it would support method Add(BaseClass)) .

              Comment

              • Pieter

                #8
                Re: List(Of clsClass) = List(Of clsSubClass)

                Yes but I should be able to Import a list of Bananas into a list of Fruits?
                But it doesn't work?

                "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
                news:218b3924-f208-4224-a99d-d3606d3fe6b5@l4 2g2000hsc.googl egroups.com...
                What exactly would you expect an import to do? You just can't treat a
                list of bananas as if it's a general list of fruit. You can create a
                new list of fruit and copy the contents of a list of bananas into it,
                of course.

                Jon


                Comment

                • Pieter

                  #9
                  Re: List(Of clsClass) = List(Of clsSubClass)

                  Ooops: The Import function is one we created ourselves: It takes a
                  BaseList(Of T) as argument.

                  "Marc Gravell" <marc.gravell@g mail.comwrote in message
                  news:d86ffb1e-cb46-4cd8-9d41-476501e6bf78@79 g2000hsk.google groups.com...
                  Well, what are you meaning by "import"? Any example code?
                  >
                  One good trick here is to use a generic method; I'll use C# syntax for
                  [my] familiarity:
                  >
                  public void DoSomething<T>( List<Tlist) where T : clsClass
                  {
                  >
                  }
                  >
                  you can now pass a List<clsClassor a List<clsSubClas s>, but you
                  ideally want to talk about "T" inside the method. You are saying "I
                  have a list of [something], where that [something] is, or is derived
                  from, clsClass".
                  >
                  Marc

                  Comment

                  • Jon Skeet [C# MVP]

                    #10
                    Re: List(Of clsClass) = List(Of clsSubClass)

                    On Jul 15, 2:32 pm, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:
                    Ooops: The Import function is one we created ourselves: It takes a
                    BaseList(Of T) as argument.
                    And what does it do, exactly? It's hard to say why something doesn't
                    work without seeing it...

                    Jon

                    Comment

                    • =?Utf-8?B?U3VydHVyWg==?=

                      #11
                      RE: List(Of clsClass) = List(Of clsSubClass)

                      This code should do it. MyList1 will be a different List to MyList2, but the
                      elements inside will be the same. Changes to the membership of MyList2 will
                      not be reflected in MyList1, but changes to properties of the members in each
                      should be:

                      Dim MyList1 as New List(Of clsClass)
                      Dim MyList2 as New List(Of clsSubClass)
                      ....
                      'Copy MyList2 into MyList1
                      MyList1.Clear
                      For i As Integer = 0 To MyList2.Count -1
                      MyList1.Add MyList2.Item(i)
                      Next i

                      --
                      David Streeter
                      Synchrotech Software
                      Sydney Australia


                      "Pieter" wrote:
                      Hi,
                      >
                      I have a class clsSubClass which inherits from clsClass.
                      >
                      When I instantiate an object of clsClass (MyClass), and I instantiate an
                      object from clsSubclass (MySubClass) I can do an "MyClass = MySubclass".
                      >
                      But when I declare two generic list of them ("Dim MyList1 as List(Of
                      clsClass)" and "Dim MyList2 as List(Of clsSubClass)"), I can't do an
                      "MyList1 = MyList2".
                      >
                      Why is this exactly, and is there a way to implement this behaviour?
                      >
                      >
                      Thanks a lot in advance,
                      >
                      >
                      Pieter
                      >
                      >
                      >

                      Comment

                      • Marc Gravell

                        #12
                        Re: List(Of clsClass) = List(Of clsSubClass)

                        On 15 Jul, 14:32, "Pieter" <pieterNOSPAMco u...@hotmail.co mwrote:
                        Ooops: The Import function is one we created ourselves: It takes a
                        BaseList(Of T) as argument.
                        So the generic method approach can be used (see below, again, using C#
                        syntax). Alternatively, in .NET 3.5 the LINQ "Cast" method can be used
                        as a one-liner, even with a regular List<T>:

                        fruits.AddRange (bananas.Cast<F ruit>());

                        Marc

                        == code ===

                        public class MyList<T: List<T{
                        public void Import<TOther>( IEnumerable<TOt herlist)
                        where TOther : T {
                        foreach (TOther other in list) {
                        Add(other);
                        }
                        }
                        }
                        abstract class Fruit { }
                        class Banana : Fruit { }
                        class Tomato : Fruit { }

                        static void Main() {
                        MyList<Bananaba nanas = new MyList<Banana>( );
                        bananas.Add(new Banana());
                        bananas.Add(new Banana());

                        MyList<Fruitfru its = new MyList<Fruit>() ;
                        fruits.Add(new Tomato());
                        fruits.Import(b ananas);
                        }

                        Comment

                        Working...