Generics, IEnumerable and Polymorphism

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

    #1

    Generics, IEnumerable and Polymorphism

    It looks to me that in using that in creating generic IEnumerables, you
    lose polymorphic capabilities.

    Consider this pseudo code:

    abstract class BaseClass;

    class DerivedClassSpe cialFunction1 : BaseClass
    class DerivedClassSpe cialFunction2 : BaseClass

    class Function1Implem entationA : DerivedClassSpe cialFunction1
    class Function1Implem entationB : DerivedClassSpe cialFunction1


    List<BaseClass> mylist = new List<BaseClass>

    // assume the above list gets populated with a mix of the above classes

    foreach (BaseClass item in mylist)
    {
    DerivedClassSpe cialFunction1 derivedItem = item as
    DerivedClassSpe cialFunction1;

    if (derivedItem != null)
    {
    derivedItem.Cal lSpecialFunctio n();
    }
    }

    This allows me to iterate through a list of objects all subclassed from
    the same absrtact class and then, for only specific types, call some
    function. The function called is the correct function for the instance
    type.

    I then tried to create an IEnumerator method to try to clean this up a
    bit (hoping to avoid testing for the right type everytime (and also
    checking for null).

    My iterator looked something like this:

    public IEnumerator<Der ivedClassSpecia lFunction1>
    GetSpecialFunct ion1ClassesOnly ()
    {
    foreach (BaseClass item in mylist)
    {
    if (item is DerivedClassSpe cialFunction1) yield return item;
    }
    }


    So, later if I use this enumerator in a foreach call like this:

    foreach (DerivedClassSp ecialFunction1 item in
    GetSpecialFunct ionClassesOnly( ))
    {
    item.CallSpecia lFunction();
    }

    This does not work correctly. Instead of calling the
    Function1Implem entationA version of CallSpecialFunc tion(), it always
    uses the DerivedClassSpe cialFunction version.

    Is there a way to do what I want and still use custom enumerators? I
    want to selectively filter on type, but retain the polymorphic
    abilities of subclasses from that type.

    Thanks!

    Mike

  • Mattias Sjögren

    #2
    Re: Generics, IEnumerable and Polymorphism

    Mike,
    [color=blue]
    >This does not work correctly. Instead of calling the
    >Function1Imple mentationA version of CallSpecialFunc tion(), it always
    >uses the DerivedClassSpe cialFunction version.[/color]

    That's not what I'm seeing. Below is a cleaned up version of your code
    that actually compiles. The output is

    DerivedClassSpe cialFunction1
    Function1Implem entationA
    Function1Implem entationB

    which is what I expect and seems perfectly polymorphic. If you get
    something else please post your complete code. Here's mine:

    using System;
    using System.Collecti ons.Generic;

    abstract class BaseClass
    {
    public virtual void CallSpecialFunc tion() {
    Console.WriteLi ne("BaseClass") ; }
    }

    class DerivedClassSpe cialFunction1 : BaseClass
    {
    public override void CallSpecialFunc tion() {
    Console.WriteLi ne("DerivedClas sSpecialFunctio n1"); }
    }

    class DerivedClassSpe cialFunction2 : BaseClass
    {
    public override void CallSpecialFunc tion() {
    Console.WriteLi ne("DerivedClas sSpecialFunctio n2"); }
    }

    class Function1Implem entationA : DerivedClassSpe cialFunction1
    {
    public override void CallSpecialFunc tion() {
    Console.WriteLi ne("Function1Im plementationA") ; }
    }

    class Function1Implem entationB : DerivedClassSpe cialFunction1
    {
    public override void CallSpecialFunc tion() {
    Console.WriteLi ne("Function1Im plementationB") ; }
    }

    class Test
    {
    static List<BaseClass> mylist = new List<BaseClass> ();

    public static IEnumerable<Der ivedClassSpecia lFunction1>
    GetSpecialFunct ion1ClassesOnly ()
    {
    foreach (BaseClass item in mylist)
    {
    DerivedClassSpe cialFunction1 dcsf1 = item as
    DerivedClassSpe cialFunction1;
    if (dcsf1 != null) yield return dcsf1;
    }
    }

    static void Main()
    {

    mylist.Add(new DerivedClassSpe cialFunction1() );
    mylist.Add(new DerivedClassSpe cialFunction2() );
    mylist.Add(new Function1Implem entationA());
    mylist.Add(new Function1Implem entationB());

    foreach (DerivedClassSp ecialFunction1 item in
    GetSpecialFunct ion1ClassesOnly ())
    {
    item.CallSpecia lFunction();
    }

    }
    }


    Mattias

    --
    Mattias Sjögren [C# MVP] mattias @ mvps.org
    http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
    Please reply only to the newsgroup.

    Comment

    • Joanna Carter [TeamB]

      #3
      Re: Generics, IEnumerable and Polymorphism

      "Mike" <mikee.jones@mb na.com> a écrit dans le message de news:
      1135101656.6158 25.21530@g14g20 00...legro ups.com...

      | So, later if I use this enumerator in a foreach call like this:
      |
      | foreach (DerivedClassSp ecialFunction1 item in
      | GetSpecialFunct ionClassesOnly( ))
      | {
      | item.CallSpecia lFunction();
      | }
      |
      | This does not work correctly. Instead of calling the
      | Function1Implem entationA version of CallSpecialFunc tion(), it always
      | uses the DerivedClassSpe cialFunction version.

      I used the following code :

      public abstract class BaseClass
      {
      }

      public class DerivedClassSpe cialFunction1 : BaseClass
      {
      public virtual void CallSpecialFunc tion()
      {
      }
      }

      public class DerivedClassSpe cialFunction2 : BaseClass
      {
      }

      public class Function1Implem entationA : DerivedClassSpe cialFunction1
      {
      public override void CallSpecialFunc tion()
      {
      }
      }

      public class Function1Implem entationB : DerivedClassSpe cialFunction1
      {
      public override void CallSpecialFunc tion()
      {
      }
      }

      private List<BaseClass> mylist = new List<BaseClass> ();

      public IEnumerator<Der ivedClassSpecia lFunction1>
      GetSpecialFunct ion1ClassesOnly ()
      {
      foreach (BaseClass item in mylist)
      {
      if (item is DerivedClassSpe cialFunction1)
      yield return (DerivedClassSp ecialFunction1) item;
      }
      }


      Then I use dthe following test code :

      private void button1_Click(o bject sender, EventArgs args)
      {
      mylist.Add(new Function1Implem entationA());
      mylist.Add(new DerivedClassSpe cialFunction2() );
      mylist.Add(new Function1Implem entationB());
      mylist.Add(new Function1Implem entationA());

      IEnumerator<Der ivedClassSpecia lFunction1> iter =
      GetSpecialFunct ion1ClassesOnly ();

      while (iter.MoveNext( ))
      iter.Current.Ca llSpecialFuncti on();

      This then works perfectly calling the correct overriden method only on those
      items that are derived from DerivedClassSpe cialFunction1.

      If I change the test code to the following :

      foreach (DerivedClassSp ecialFunction1 item in
      GetSpecialFunct ion1ClassesOnly ())
      {
      item.CallSpecia lFunction();
      }

      .... then this doesn't even compile ! You can't use foreach on an
      IEnumerator, only on an IEnumerable or an object that has a GetEnumerator()
      method.

      Joanna

      --
      Joanna Carter [TeamB]
      Consultant Software Engineer


      Comment

      • Joanna Carter [TeamB]

        #4
        Re: Generics, IEnumerable and Polymorphism

        "Joanna Carter [TeamB]" <joanna@not.for .spam> a écrit dans le message de
        news: Okg%23FlZBGHA.3 604@TK2MSFTNGP0 9.phx.gbl...

        | If I change the test code to the following :
        |
        | foreach (DerivedClassSp ecialFunction1 item in
        | GetSpecialFunct ion1ClassesOnly ())
        | {
        | item.CallSpecia lFunction();
        | }
        |
        | ... then this doesn't even compile ! You can't use foreach on an
        | IEnumerator, only on an IEnumerable or an object that has a
        GetEnumerator()
        | method.

        My bad, I forgot to declare the GetSpecialFinct ion1ClassesOnly method as
        static.

        Like Mattias, Now I find this code works perfectly as expected.

        Did you declare your CallSpecialFunc tion() as virtual and override where
        necessary ??

        Joanna

        --
        Joanna Carter [TeamB]
        Consultant Software Engineer


        Comment

        • gummycat@comcast.net

          #5
          Re: Generics, IEnumerable and Polymorphism

          Thanks Mattias and Joanna,

          I hate to say it, but turns out the problem was hidden elsewhere and
          this so-called "loss of polymorphism" was the false symptom. I did not
          trace through the code properly and mis-diagnosed the problem.

          Turns out my IEnumerable code was all in perfect working order. This
          is a relief as I had fooled myself into thinking a core OO concept had
          been trashed by M$... but alas, it is just my ego that is trashed! ;-)

          The system I am working on is complex (aren't they all, right?). There
          is a method that looks for a context object that is transitory. If it
          finds a current context, it will return an IEnumerable from this
          context, otherwise it will build it's own empty one. Hard to explain
          all the details on why, but the context was being queried at a time
          when it could not have been set. This was my mistake. I assumed it
          would be there at a time that it could not be. As a result, downstream
          in the code, the symptom appeared to be a loss of polymorphism. Once I
          traced through the code patiently and properly, it was plain as day for
          me.

          Thanks so much for taking the time to respond to my query. It was your
          quick responses that got me to stop thinking it was a polymorphism
          issue and to start looking for the real problem!

          What a great community!

          Thanks!

          Mike

          Comment

          Working...