What does this code print?
What does this code print, and why?
using System;
public class A
{
public void F(int i)
{
Console.WriteLine("A: {0}", i);
}
}
public class B: A
{
public void F(object o)
{
Console.WriteLine("B: {0}", o);
}
}
public class Test
{
public static void Main()
{
B b = new B();
b.F(1);
}
}
what about this code?
using System;
public class A
{
public void F(short i)
{
Console.WriteLine("A: {0}", i);
}
}
public class B: A
{
public void F(int i)
{
Console.WriteLine("B: {0}", i);
}
}
public class Test
{
public static void Main()
{
short val = 15;
B b = new B();
b.F(val);
}
}
Comments
Anonymous
December 12, 2005
Wow. C# shadows by default in child classes?Anonymous
December 12, 2005
Being a VB.NET'er, I would have assumed A: would appear every time (assuming Overloads rather than Shadows is used, as it almost always is).
I'm at a loss to understand why C# does it this way.Anonymous
December 12, 2005
I checked, and it seems that on both cases it calls the B method.
This is surprising, since I thought that shadowing wouldn't interfere with overloading.Anonymous
December 12, 2005
I can understand a short being an int. But why is an int an object?Anonymous
December 12, 2005
Assuming C3 follows the same rules as C++ (generally a good assumption), a method in a derived class always hides a same-named method in the base case, regardless of parameter types.
The logic here is that if A:F did not exist, then B:F would be called. Hence it is possible that A:F was added to class A after class B was written, and just recompiling with the new A code should not change the behavior of B:F in this way.
In C++, to make A:F available in a B object, we'd need to define B like this:
class B: public A
{
public:
using A::F;
void F(object i)
{
Console.WriteLine("B: {0}", i);
}
};
That would make both F(int) & F(Object) equivalent over the overload resolution rules, and the best fit would be used. I'm not sure what's the C# syntax.Anonymous
December 12, 2005
So this is legal?
object o = new object(1);Anonymous
December 12, 2005
Maurits:
nope -
object o = new object(1);
is not legal but:
object o = new object(); o = 1;
is legal.
Yes - an object can hold anything - even value types.
Regarding the original question - I would also think both would print the B-version of the method. Like the previous posters said - it looks like a case of shadowing.Anonymous
December 12, 2005
Pretty good example of why, for most people, shadowing shouldn't be used, certainly at least for public methods.
interesting to note that
public class A
{
public void F(short i)
{
Console.WriteLine("A: {0}", i);
}
}
public class B: A
{
public void F(short i)
{
Console.WriteLine("B: {0}", i);
}
}
Creates a compile warning but neither of these examples do (in VS 2003 at least).
I think they should personally - any thing which needs more than 10 seconds (or a reference book) to work out is almost certainly a bad idea to use :)
This example displays how
overloading / shadowing / type coercion and automatic boxing all interact. A sensible suggestion for readers is don't let them :)Anonymous
December 13, 2005
This is easy for all C++ developers: methods in B shadow (hide) methods in A. However, as some of your comments show, it is unexpected for a fair number of people. Interesting...
Unlike one of the suggestions to NOT LET developer do this, I would suggest that you issue a warning, at least on a higher warning levels if not even on a default level.
I actually tried the code on both 2003 and 2005 to see if there will be any warning and was surprised to find none. I then translated the code to C++ (non-clr) and got no warning there. Hmm, I was sure I saw once this warning ("method X shadows method Y in the base class").Anonymous
December 13, 2005
>> However, as some of your comments show, it is unexpected for a fair number of people.
Unexpected because in VB.NET it would warn you about this (making you choose to Shadow or Overloads).
I find it fascinating that C# doesn't give you the choice.Anonymous
December 15, 2005
My guess went totally wrong and having all kind of "C++ surprises" in C# should atleast have some easily toggleable informal message about when those are influencing the code.Anonymous
December 15, 2005
Joku,
Do you feel the same way after reading my "make it a warning" post?Anonymous
December 15, 2005
Yes and in my application there are Exceptions (bad), Errors (program will continue), Warnings (user should do something about it or face the consequences later), Informal messages (good to know).
But perhaps FxCop is something better suited for adding this type of "good to know" messages, but... I'll be honest. I do not use it all the time. So by the time I might turn it on, there might already be bugs lurking by such surprising as this that could have been avoided if there was such "good to know" or informal messages readily seen in the IDE, but ones which you could toggle of on a per message basis straight from the view (without going to project properties).Anonymous
January 04, 2006
Well in the Short example short val is implicidly casted as int and so B class F method can be called, if there is no implicid cast , like
public class A
{
public void F(long i)
{
Console.WriteLine("A: {0}", i);
}
}
public class B: A
{
public void F(int i)
{
Console.WriteLine("B: {0}", i);
}
}
public class Test
{
public static void Main()
{
long val = 15;
B b = new B();
b.F(val);
}
}
base class B method is called.Anonymous
October 03, 2006
PingBack from http://www.hedgate.net/articles/2005/12/15/extension-methods-and-method-overload-resolutionAnonymous
September 18, 2007
PingBack from http://www.hedgate.net/articles/2006/10/04/extension-methods-and-method-overload-resolution/