Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Subtle refactoring C# inheritance gotcha

Subtle refactoring C# inheritance gotcha

Scheduled Pinned Locked Moved Clever Code
csharpregexoopcode-review
4 Posts 3 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    vineas
    wrote on last edited by
    #1

    I did some refactoring a while back on some C# code that was originally mine, but someone else had taken over and added some methods. I hit a gotcha that took a bit to figure out what was going on. The code before the refactor was something like:

    public class Foo
    {
      // my original method
      public virtual void Method(string str)
      {
        // do something
      }
    
      // new method
      public void Method(string str, params object[] stuff)
      {
        if (stuff == null)
          Method(str);
        else
          // call something else
      }
    }
    

    After the refactor, it looked something like

    public class FooBase
    {
      // my original method
      public virtual void Method(string str)
      {
        // do something
      }
    }
    
    public class Foo : FooBase
    {
      // new method
      public void Method(string str, params object[] stuff)
      {
        if (stuff == null)
          Method(str);
        else
          // call something else
      }
    }
    

    When I ran it, calling Foo.Method("string") would end up causing an infinite loop. After some serious head scratching, I figured out that the method resolver looks at the actual type first to find a match, and looks at the base only if it couldn't find one at that level. Inside of Foo.Method, it calls Method(str) - which would end up resolving to the method with the signature of Method(string str, params object[] stuff), not Method(string str). It's not quite the way I expected it to work, but thinking about it now that's pretty much how it would have to work in order to resolve overrides correctly. I ended up having to change the name of Method(string str, params object[] stuff) because there was something that inherited from Foo and overrode the original Method - so calling base.Method(str) there would simply not work. I would have changed it anyway though, because the new method really wasn't an overload of Method, but did some other things and shouldn't have the same name (it actually belonged in a separate class altogether, but that's a different story).

    ----- In the land of the blind, the one eyed man is king.

    S P 2 Replies Last reply
    0
    • V vineas

      I did some refactoring a while back on some C# code that was originally mine, but someone else had taken over and added some methods. I hit a gotcha that took a bit to figure out what was going on. The code before the refactor was something like:

      public class Foo
      {
        // my original method
        public virtual void Method(string str)
        {
          // do something
        }
      
        // new method
        public void Method(string str, params object[] stuff)
        {
          if (stuff == null)
            Method(str);
          else
            // call something else
        }
      }
      

      After the refactor, it looked something like

      public class FooBase
      {
        // my original method
        public virtual void Method(string str)
        {
          // do something
        }
      }
      
      public class Foo : FooBase
      {
        // new method
        public void Method(string str, params object[] stuff)
        {
          if (stuff == null)
            Method(str);
          else
            // call something else
        }
      }
      

      When I ran it, calling Foo.Method("string") would end up causing an infinite loop. After some serious head scratching, I figured out that the method resolver looks at the actual type first to find a match, and looks at the base only if it couldn't find one at that level. Inside of Foo.Method, it calls Method(str) - which would end up resolving to the method with the signature of Method(string str, params object[] stuff), not Method(string str). It's not quite the way I expected it to work, but thinking about it now that's pretty much how it would have to work in order to resolve overrides correctly. I ended up having to change the name of Method(string str, params object[] stuff) because there was something that inherited from Foo and overrode the original Method - so calling base.Method(str) there would simply not work. I would have changed it anyway though, because the new method really wasn't an overload of Method, but did some other things and shouldn't have the same name (it actually belonged in a separate class altogether, but that's a different story).

      ----- In the land of the blind, the one eyed man is king.

      S Offline
      S Offline
      Super Lloyd
      wrote on last edited by
      #2

      Hey, that's a good one! :cool:

      A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station.... _________________________________________________________ My programs never have bugs, they just develop random features.

      1 Reply Last reply
      0
      • V vineas

        I did some refactoring a while back on some C# code that was originally mine, but someone else had taken over and added some methods. I hit a gotcha that took a bit to figure out what was going on. The code before the refactor was something like:

        public class Foo
        {
          // my original method
          public virtual void Method(string str)
          {
            // do something
          }
        
          // new method
          public void Method(string str, params object[] stuff)
          {
            if (stuff == null)
              Method(str);
            else
              // call something else
          }
        }
        

        After the refactor, it looked something like

        public class FooBase
        {
          // my original method
          public virtual void Method(string str)
          {
            // do something
          }
        }
        
        public class Foo : FooBase
        {
          // new method
          public void Method(string str, params object[] stuff)
          {
            if (stuff == null)
              Method(str);
            else
              // call something else
          }
        }
        

        When I ran it, calling Foo.Method("string") would end up causing an infinite loop. After some serious head scratching, I figured out that the method resolver looks at the actual type first to find a match, and looks at the base only if it couldn't find one at that level. Inside of Foo.Method, it calls Method(str) - which would end up resolving to the method with the signature of Method(string str, params object[] stuff), not Method(string str). It's not quite the way I expected it to work, but thinking about it now that's pretty much how it would have to work in order to resolve overrides correctly. I ended up having to change the name of Method(string str, params object[] stuff) because there was something that inherited from Foo and overrode the original Method - so calling base.Method(str) there would simply not work. I would have changed it anyway though, because the new method really wasn't an overload of Method, but did some other things and shouldn't have the same name (it actually belonged in a separate class altogether, but that's a different story).

        ----- In the land of the blind, the one eyed man is king.

        P Offline
        P Offline
        Paulo Zemek
        wrote on last edited by
        #3

        I know you solved you issue, but you could solve the issue having an overload of the Method(string) at Foo. It will lock ugly, as you will inherit a method only to call it's base class, but the problem (considering the method should have the same name) will be solved.

        V 1 Reply Last reply
        0
        • P Paulo Zemek

          I know you solved you issue, but you could solve the issue having an overload of the Method(string) at Foo. It will lock ugly, as you will inherit a method only to call it's base class, but the problem (considering the method should have the same name) will be solved.

          V Offline
          V Offline
          vineas
          wrote on last edited by
          #4

          In this case, it made sense to have a different name, but doing that would have made the refactoring much easier. I wish I would have thought of that at the time.

          ----- In the land of the blind, the one eyed man is king.

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups