Beautiful question! I'd like to add a slightly longer explanation for those who don't do C# on a daily basis... because the question is a good reminder of name resolution issues in general.
Take the original code, slightly modified in the following ways:
- Let's print out the type names instead of comparing them as in the original expression (i.e.
return this is Sparta
).
- Let's define the interface
Athena
in the Place
superclass to illustrate interface name resolution.
- Let's also print out the type name of
this
as it is bound in the Sparta
class, just to make everything very clear.
The code looks like this:
public class Place {
public interface Athena { }
}
public class Sparta : Place
{
public void printTypeOfThis()
{
Console.WriteLine (this.GetType().Name);
}
public void printTypeOfSparta()
{
Console.WriteLine (typeof(Sparta));
}
public void printTypeOfAthena()
{
Console.WriteLine (typeof(Athena));
}
}
We now create a Sparta
object and call the three methods.
public static void Main(string[] args)
{
Sparta s = new Sparta();
s.printTypeOfThis();
s.printTypeOfSparta();
s.printTypeOfAthena();
}
}
The output we get is:
Sparta
Athena
Place+Athena
However, if we modify the Place class and define the interface Sparta:
public class Place {
public interface Athena { }
public interface Sparta { }
}
then it is this Sparta
-- the interface -- that will be available first to the name lookup mechanism and the output of our code will change to:
Sparta
Place+Sparta
Place+Athena
So we have effectively messed up with the type comparison in the MakeItReturnFalse
function definition just by defining the Sparta interface in the superclass, which is found first by the name resolution.
But why does C# chose to prioritize interfaces defined in the superclass in the name resolution? @JonSkeet knows! And if you read his answer you'll get the details of the name resolution protocol in C#.