I have following code that really does funny stuff:
class Parent {
public virtual void DoSomething(IEnumerable<string> list) {
Console.WriteLine("Parent.DoSomething(IEnumerable<string>)");
}
}
class Child : Parent {
public override void DoSomething(IEnumerable<string> list) {
Console.WriteLine("Child.DoSomething(IEnumerable<string>)");
}
public void DoSomething(IEnumerable<object> list) {
Console.WriteLine("Child.DoSomething(IEnumerable<object>)");
}
}
As you can see, the DoSomething
method in Child
is overridden correctly.
The output of the following code is very unexpected:
...
Child c = new Child();
var list = new List<string> { "Hello", "World!" };
c.DoSomething(list);
...
Prints Child.DoSomething(IEnumerable<object>)
Whereas assinging a Parent
reference to c
generates the correct output:
...
Parent c = new Child();
var list = new List<string> { "Hello", "World!" };
c.DoSomething(list);
...
Prints Child.DoSomething(IEnumerable<string>)
Why does this happen?!
C is a general purpose computer programming language developed in 1972 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system. It was named 'C' because many of its features were derived from an earlier language called 'B'.
The programs that you write in C compile and execute much faster than those written in other languages. This is because it does not have garbage collection and other such additional processing overheads. Hence, the language is faster as compared to most other programming languages.
Because C comes after B The reason why the language was named “C” by its creator was that it came after B language. Back then, Bell Labs already had a programming language called “B” at their disposal.
C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.
It happens because the C# compiler obeys the spec :)
The specification says that if any method declared in a derived type is applicable, any methods originally declared in a base class (even if they're overridden in the derived type) are removed from the set of candidates.
Now because you're using C# 4 (presumably) there's an implicit conversion from List<string>
to IEnumerable<object>
so your Child.DoSomething(IEnumerable<object>)
overload is applicable, and the compiler never really considers the one using IEnumerable<string>
.
I have an article about overloading which goes into this and some other oddities.
I advise you not to overload across type hierarchies - it's confusing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With