Subtle refactoring C# inheritance gotcha
-
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 ofMethod(string str, params object[] stuff)
, notMethod(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 ofMethod(string str, params object[] stuff)
because there was something that inherited from Foo and overrode the original Method - so callingbase.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.
-
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 ofMethod(string str, params object[] stuff)
, notMethod(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 ofMethod(string str, params object[] stuff)
because there was something that inherited from Foo and overrode the original Method - so callingbase.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.
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.
-
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 ofMethod(string str, params object[] stuff)
, notMethod(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 ofMethod(string str, params object[] stuff)
because there was something that inherited from Foo and overrode the original Method - so callingbase.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.
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.
-
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.