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 (16)

  1. Anon says:

    Wow. C# shadows by default in child classes?

  2. Matthew says:

    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.

  3. 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.

  4. I can understand a short being an int. But why is an int an object?

  5. James Curran says:

    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.

  6. So this is legal?

    object o = new object(1);

  7. 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.

  8. Matt says:

    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* 🙂

  9. 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").

  10. Matthew says:

    >> 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.

  11. Joku says:

    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.

  12. Joku,

    Do you feel the same way after reading my "make it a warning" post?

  13. Joku says:

    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).

  14. Qteeth says:

    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.