tags:

views:

3601

answers:

15

Without running this code, identify which Foo method will be called:

class A
{
   public void Foo( int n )
   {
      Console.WriteLine( "A::Foo" );
   }
}

class B : A
{
   /* note that A::Foo and B::Foo are not related at all */
   public void Foo( double n )
   {
      Console.WriteLine( "B::Foo" );
   }
}

static void Main( string[] args )
{
   B b = new B();
   /* which Foo is chosen? */
   b.Foo( 5 );
}

Which method? And why? No cheating by running the code.

I found this puzzle on the web; I like it and I think I'm going to use it as an interview question...Opinions?

EDIT: I wouldn't judge a candidate on getting this wrong, I'd use it as a way to open a fuller discussion about the C# and CLR itself, so I can get a good understanding of the candidates abilities.

Source: http://netpl.blogspot.com/2008/06/c-puzzle-no8-beginner.html

+5  A: 

Console.WriteLine( "B::Foo");

Because it will cast automatictly and use the first without going further in the inheritance.

I do not think it's a good interview question but it can be funny to try to solve without compiling the code.

Daok
Only if it can cast without losing precision, such as int -> double, if they were reversed, it would call the base method.
FlySwat
You are right. The example is with 5 so nothing in the precision is lost :)
Daok
The CS geek in me is crying. You *DO* lose precision when you convert int->double. A double does not exactly represent an integer, if you were to continually multiply the double by 10 eventually you would see errors creep in.
tloach
That's not really the same as losing precision - you lose nothing converting int to double and back again. If you then do some maths with that double you'll get back something else.
Keith
+36  A: 

I really wouldn't use this as an interview question. I know the answer and the reasoning behind it, but something like this should come up so rarely that it shouldn't be a problem. Knowing the answer really doesn't show much about a candidate's ability to code.

Note that you'll get the same behaviour even if A.Foo is virtual and B overrides it.

If you like C# puzzles and oddities, I've got a few too (including this one).

Jon Skeet
A: 

A because of overloading and inheritance, very nice question by the way, it's nice and simple if you know the language.

chills42
unlike you :)(the answer is B, not what you'd expect,and not what you'd get with other languages).
gbjbaanb
You get B with C++ too. In C++ name resolution is always performed before overload resolution, much to the confusion of people who try to override only one of a collection of overloaded functions.
Steve Jessop
A: 

Interesting... I didn't know about the automatic casting... That's a bit odd actually.

chills42
+4  A: 

Another vote against using it, but for a different reason.

When put on the spot like this, a lot of really good programmers would come up with the wrong answer, but not because they don't know the concepts or couldn't figure it out. What happens is that they'll see something like this and think, "Aha, trick question!", and then proceed to out-think themselves in the response. This is especially true in an interview setting where they don't have the benefit of the IDE or Google or any other of the other helps a programmer takes for granted in their day to day programming.

Joel Coehoorn
+17  A: 

Too hard? No, but what is your goal in the question? What are you expecting to get from your interviewee? That they know this particular syntactic quirk? That either means that they've studied the spec/language well (good for them) or that they've run into this problem (hopefully not from what they wrote, but if they did - yikes). Neither case really indicates that you've got a solid programmer/engineer/architect on your hand. I believe that what's important is not the question but the discussion surrounding the question.

When I interview candidates, I usually ask one deceptively simple question which is based on a language semantic quirk - but I don't care if my interviewee knows it because that semantic quirk allows me to open up a lot of avenues that allow me to find out if my candidate is methodical, their communication style, if they're willing to say "I don't know", are they capable of thinking on their feet, do they understand language design and machine architecture, do they understand platform and portability issues - in short, I'm looking for a lot of ingredients that all add up to "do they get it?". This process takes an hour or more.

In the end, I don't actually care about whether they know the answer to my question - the question is a ruse to let me get all the rest of that information indirectly without ever having to ask. If you don't have a valuable ulterior in this question, don't bother even asking it - you're wasting your time and your candidate's time.

plinth
Best interviewer I've encountered quizzed me for a couple hours on C# questions knowing that I don't know C# (but I do know java and C++). I got an offer based on my ability to reason the most likely answers
tloach
+9  A: 

Couldn't agree more with Joel there. I have 20+ years experience design and coding, and the first thing I thought of when I saw that was: It won't even compile.

I made that assumption because I try to avoid overloads that differ by only a single datatype, and in looking at the code didn't even pick up on the int/double difference; I assumed there needed to be a new operator to allow a redefinition in B.

In point of fact I had used a library a fellow programmer created for handling some text file generation that was a bit confusing because one of the methods had 8 different overloads and two of them differed only by datatype on the last argument. One was string and one was char. The likelihood that the value needed for the string version of the parameter was one character long was pretty good so hopefully you can see where this is headed. We had a devil of a time debugging problems because the consumer of the library inadvertently triggered the wrong call because of quoting differences, single versus double.

Moral of the story, be grateful that the candidate doesn't know the answer because it may indicate good coding habits.

Bill
It sounds like you don't do a lot of inheritance in your design. Overloading methods of the same name that differ by a parameter type isn't uncommon.
Simucal
I too, just like you Bill, prefer a programmer who would say "I never stumbled upon such a case before" than one that would know the answer right away.
Andrei Rinea
Simucal, we do a great deal of inheritance. I'm not sure why method overloading would be considerd a hallmark of inheretance. Maybe you are referring more to operator overloads and not method overloads, which we do a great deal of and are more clearly recognizable in code with the operator keyword.
Bill
In my experience, operator overloads are a code smell, and a huge one at that. Method overloads are pretty common, especially for convenience.
Robert C. Barth
+2  A: 

This smacks of a trick question to me. If you've been using the language for long enough, you've probably run into the problem and know the answer; but how long is long enough?

It's also a question where your background might work against you. I know in C++ the definition in B would hide the definition in A, but I have no idea if it works the same in C#. In real life, I'd know it was a questionable area and try to look it up. In an interview I might try to guess, having been put on the spot. And I'd probably get it wrong.

Mark Ransom
In real life I would try it and see what happened ;)
tloach
+2  A: 

use it as a question only as long as you expect the candidate to tell you his thought processes as he describes what he thinks should be happening. Who cares about the right and wrongness of actual code in question - in the real world, the candidate would find code like this, find it not working and debug it with a combination of debugger and writeline calls, so its a useless question if you want candidates who know (or guess) the right answer.

But those who can explain what they think would happen, that's a different matter. Hire them even if they get it wrong.

gbjbaanb
+2  A: 

I think it's a terrible question. I think any question is a terrible question when the real answer is "Run it and see!"

If I needed to know this in real life, that's exactly what I'd do: Create a test project, key it in, and find out. Then I don't have to worry about abstract reasoning or the finer points in the C# spec.

Just today I ran into such a question: If I fill the same typed DataTable twice with the same row, what will happen? One copy of the row, or two? And will it overwrite the first row even if I've changed it? I thought about asking someone, but I realized I could easily fire up a test project I already had that used DataSets, write a small method, and test it out.

Answer:

...ah, but if I tell you, you'll miss the point. :) The point is, in programming you don't have to leave these things as hypotheticals, and you shouldn't if they can be reasonably tested.

So I think it's a terrible question. Wouldn't you prefer to hire a developer who'll try it out and then know what happens, rather than a developer who'll try to dredge it up from his fading memory, or who'll ask someone else and accept an answer that might be wrong?

Kyralessa
I don't think "run it and see" is all there is to it. There exist code snippets which give different results on different compiler/runtime versions (although this isn't one of them). "It worked on my machine" isn't an ideal position to take when my code fails further down the line.
Steve Jessop
My usual approach would be first to run it to see what I get, and then with that knowledge to examine the specification to see whether what I got is guaranteed to happen always.
Steve Jessop
And yet...you can also "run it and see" on those other compilers or versions! And if "it works on my machine" isn't sufficient, that's obviously because when you "run it and see" on someone else's machine, it doesn't work. Ultimately real-world testing will always trump theory.
Kyralessa
+3  A: 

This actually is a trick question.

The answer is ambiguous as to what "should" happen. Sure, the C# compiler takes it out of the realm of ambiguity to the concrete; however, since these methods are overloading one another, and are neither overriding nor shadowing, it is reasonable to assume that the "best argument fit" should apply here, and therefore conclude that it is A::Foo(int n) that should be called when provided an integer as an argument.

To prove that what "should" happen is unclear, the exact same code when run in VB.NET has the opposite result:

Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
        Dim b As New B
        b.Foo(5)   ' A::Foo
        b.Foo(5.0) ' B::Foo
    End Sub
End Class

Class A
    Sub Foo(ByVal n As Integer)
        MessageBox.Show("A::Foo")
    End Sub
End Class

Class B
    Inherits A

    Overloads Sub Foo(ByVal n As Double)
        MessageBox.Show("B::Foo")
    End Sub
End Class

I realize that I am opening up the opportunity for the C# programmers to "bash" VB.NET for not complying with C# . But I think one could make a very strong argument that it is VB.NET that is making the proper interpretation here.

Further, IntelliSense within the C# IDE suggests that there are two overloads for the class B (because there are, or at least should be!), but the B.Foo(int n) version actually can't be called (not without first explicitly casting to a class A). The result is that the C# IDE is not actually in synch with the C# compiler.

Another way of looking at this is that the C# compiler is taking an intended overloads and turning it into a shadowed method. (This doesn't seem to be the right choice to me, but this is obviously just an opinion.)

As an interview question, I think that it can be ok if you are interested in getting a discussion about the issues here. As for getting it "right" or "wrong", I think that the question verges on a trick question that could be easily missed, or even gotten right, for the wrong reasons. In fact, what the answer to the question "should be" is actually very debatable.

Mike Rosenblum
+1  A: 

That's a ridiculous question to ask - I could answer it in < 60 seconds with Snippet Compiler, and if I ever worked in a code base that depended on the functionality - it'd be quickly refactored out of existence.

The best answer is "that's a stupid design, don't do that and you won't have to parse the language spec to know what it's going to do".

If I was the interviewee, I'd think very highly of your geek trivia cred, and would perhaps invite you to the next game of Geek Trivial Pursuit. But, I'm not so sure I'd want to work with/for you. If that's your goal, by all means ask away.

  • Note that in an informal situation, geek trivia like this can be fun and entertaining. But, to an interviewee, an interview is anything but fun or informal - why further agitate it with trivial questions that the interviewee doesn't know if you take seriously or not?
Mark Brackett
So your answer is basically that it doesn't matter if someone knows how their programming language works?
BobbyShaftoe
@Bobby - at the extreme edges? Yeah, I'd say it doesn't really matter. I'd much rather someone who can reason, than a spec geek.
Mark Brackett
+4  A: 

Not really fair as an interview question, as it's a bit of a trick question. The good answer I'd want from an interviewee would be more along the lines of "That needs refactoring".

Unless you're looking to hire someone to work on compilers I'm not sure that you need to go that much in depth into the CLR.

For interview questions I look for things that show the coder's level of understanding in their answer. This is more of an oddity/puzzle.

Keith
Yours is the best answer. When faced with such a question I would try to find an answer but ultimately express my opinion that it is a bad practice to have such puzzles in code and opt for another solution.
Developer Art
A: 

Try a similar sample given below:

class Program
{
    class P
    {}
    class Q : P
    {}

    class A 
    { 
        public void Fee(Q q)
        {
            Console.WriteLine("A::Fee");
        }
    }

    class B : A 
    {   
        public void Fee(P p)
        {
            Console.WriteLine("B::Fee");
        }
    }

    static void Main(string[] args) 
    { 
        B b = new B();   
        /* which Fee is chosen? */  

        b.Fee(new Q());
        Console.ReadKey();
    }
}

The compiler seems to prefer linking the "b.Fee()" call to an available method of the type rather than an inherited method (method of a base type) if the parameter can be implicitly cast to match any such method. I.e. implicit casting of the parameter takes precedence over base class method linking.

Though honestly I find the opposite as more intuitive, because for me an inherited method is just as good as a directly introduced method.

A: 

This will return B::Foo

Anwar