A very interesting bit of code caught my eye yesterday courtesy of Peter Ritchie (example clarified by Jon Skeet) in one of the mailing lists I am subscribed to, it’s a real gem.
Without running it … what does this code do and why?
|
using System;
class Base {
public virtual void Foo(string x) {
Console.WriteLine("Base.Foo(string");
}
}
class Derived : Base {
public override void Foo(string x) {
Console.WriteLine("Derived.Foo(string)");
}
public virtual void Foo(object o) {
Console.WriteLine("Derived.Foo(object)");
}
}
class Test {
static void Main() {
new Derived().Foo("this is a string");
}
} |
A) it prints Derived.Foo(string) because it is the best overload found
B) it prints Derived.Foo(object) because we never typed the string passed in and assumes it to be an object
C) it prints Derived.Foo(object) because it ignores the string overload
D) it prints Derived.Foo(object) because the CLR is broken
E) it prints Base.Foo(string)
Space deliberately left so you have to scroll …
C) It prints Derived.Foo(object). Intuitive eh? I think this might just be added to my list of interview questions. The overridden member is not considered when resolving the overload on the derived class as it is defined on the base.
I had to break out my copy of the C# specification to verify this is correct but it is.
This is not something that is controlled by the CLR as we can see by looking at the IL in question
.method private hidebysig static void Main() cil managed { .entrypoint .maxstack 8 L_0000: nop L_0001: newobj instance void Derived::.ctor() L_0006: ldstr "this is a string" L_000b: callvirt instance void Derived::Foo(object) L_0010: nop L_0011: ret } |
VB.NET will not emit the same IL given the following code ..
|
MustInherit Class base
Public MustOverride Sub Foo(ByVal s As String)
End Class
Class derived
Inherits base
Public Overloads Sub Foo(ByVal o As Object)
Console.WriteLine("Derived:Foo object")
End Sub
Public Overrides Sub Foo(ByVal s As String)
Console.WriteLine("Derived:Foo string")
End Sub
End Class
Module Module1
Sub Main()
Dim d As New derived()
d.Foo("test")
End Sub
End Module |
Prints Derived:Foo string
I wonder how many of the code converters will pick this up? J Not one I have tested so far, probably because there is no good way to convert this code (you could feasably go through and CType it to an object but you need some pretty in depth information about the types to do it) … This is also something to watch out for when dealing with CodeDOM as the same CodeDOM tree will express differring behaviors.
Posted
07-01-2006 2:34 AM
by
Greg