22
\$\begingroup\$

I hope this kind of "riddle" is ontopic in Programming Puzzles & Code Golf.

Give an example of a situation where the C# method below returns false:

public class Giraffe : Animal
{
  public bool Test()
  {
    return this is Giraffe;
  }
}

Rules: The code lines above must not be changed in any way, but you would put the code into an application so that the "project" compiles and the method is called. When run, the method must return false. The solution I have in mind, does not emit its own IL at run-time or similar "exotic" things, it's an ordinary instance method call.

\$\endgroup\$
  • 2
    \$\begingroup\$ By "the method is called", do you mean to say that Giraffe giraffe = new Giraffe(); giraffe.Test(); must occur somehow so that the line in that method is, in fact, executed? \$\endgroup\$ – Jesse C. Slicer Aug 2 '13 at 15:22
  • \$\begingroup\$ @JesseC.Slicer Yes, in the solution I have in mind, that line does occur. Of course, it could be interesting to see other solutions that I haven't thought of, too. So if you have something, do post it! \$\endgroup\$ – Jeppe Stig Nielsen Aug 2 '13 at 15:25
  • 1
    \$\begingroup\$ Well, my simple solution looks more like Animal giraffe = new Giraffe(); giraffe.Test(); and the parent class Animal has a Test() method which returns false. That's cheating a bit as it calls the parent class method rather than Giraffe's. But the call site looks the same. \$\endgroup\$ – Jesse C. Slicer Aug 2 '13 at 15:28
  • \$\begingroup\$ @JesseC.Slicer Ah, I see. I would argue that with your "solution" it is not the "method below" (as it says in my problem) that returns false, so I wouldn't say it was a full solution. But interesting still. My solution does not have any method hiding (hint), but as I said, other solutions could be interesting too. \$\endgroup\$ – Jeppe Stig Nielsen Aug 2 '13 at 15:32
28
\$\begingroup\$

Yay, found it!

public class Animal
{
    public class Giraffe { } // 1
}
public class Giraffe : Animal // 2
{
    public bool Test()
    {
        return this is Giraffe;
    }
}

Since Giraffe 1 is a member of Animal, and Giraffe 2 is one level further out, the name Giraffe in the is test refers to the former (section 7.6.2 in the C# 5 spec).

Visual Studio shows a warning for this is Giraffe:

The given expression is never of the provided type

which is obviously true, since it's the whole point :)

You cannot put Giraffe 1 directly inside Giraffe 2, because

member names cannot be the same as their enclosing type

– but such a rule does not exist for derived classes.

Neat problem, took me a while.

\$\endgroup\$
  • 11
    \$\begingroup\$ Well played sir \$\endgroup\$ – Marc Gravell Aug 2 '13 at 18:53
  • 2
    \$\begingroup\$ Yes, this was the solution I had in mind! So there are two types, one nested TheNamespace.Animal.Giraffe which because of inheritance can also be called TheNamespace.Giraffe.Giraffe, and one non-nested TheNamespace.Giraffe. Your reference to the C# spec is relevant! You can get rid of the compiler warning. Just change the nested type of the base class from class to interface. In that case someone might derive further from the non-nested Giraffe and implement the nested Giraffe as well, so in that case the compiler can't complain; it's a "fair" type check. \$\endgroup\$ – Jeppe Stig Nielsen Aug 3 '13 at 6:27
  • 1
    \$\begingroup\$ I don't understand this solution — that may be because I don't know C# much. I don't like this playing on names. I find the solution of @JesseC.Slicer much cleverer. \$\endgroup\$ – Nicolas Barbulesco May 30 '14 at 13:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.