Scott Dorman wrote:
Defining the member in an interface doesn't imply that it is virtual at all.
Aha! This is the root of my confusion. I was assuming that a C# interface was the same as a C++ interface (i.e. a collection of pure virtual/abstract methods). I remembered reading in the O'Reilly "C# Essentials" book that a C# interface was simply a syntactic shortcut for a bunch of abstract members in an abstract class but their exact wording was "similar to" :| The output from the following code gave me a surprise:
interface I
{
void foo( string msg ) ;
}
class A : I
{
public void foo( string msg ) { System.Console.WriteLine( msg+" -> A::foo" ) ; }
}
class B : A
{
public void foo( string msg ) { System.Console.WriteLine( msg+" -> B::foo" ) ; }
}
static void Main()
{
B b = new B() ;
((I)b).foo( "Static type I" ) ;
((A)b).foo( "Static type A" ) ;
((B)b).foo( "Static type B" ) ;
}
--- OUTPUT ---
Static type I -> A::foo
Static type A -> A::foo
Static type B -> B::foo
In C++, the B::foo() method would've been called every time. No wonder I thought foreach appeared to be ignoring the IEnumerable's in the inheritance hierarchy. In every other OO language I've worked with, to get access to GetEnumerator() you would have to go through the IEnumerable but in C#, deriving from an interface seems to be little more than a directive to the compiler telling it that certain methods need to defined i.e. it doesn't really affect the class as such (e.g. by causing the layout of the v-table to change, or whatever C# uses). Playing around a little with the definition of B:
class B : A,I
{
void foo( string msg ) { System.Console.WriteLine( msg+" -> B::foo" ) ; }
}
--- OUTPUT ---
Static type I -> A::foo
Static type A -> A::foo
Static type B -> A::foo
That's weird, but I think because B::foo() is not public:
class B : A,I
{
public void foo( string msg ) { System.Console.WriteLine( msg+" -> B::foo" ) ; }
}
--- OUTPUT ---
Static type I -> B::foo
Static type A -> A::foo
Static type B -> B::foo
And how about these two:
class B : A,I
{
void foo( string msg ) { System.Console.WriteLine( msg+" -> B::foo" ) ; }
void I.foo( string msg ) { System.Console.WriteLine( msg+" -> B::foo 2" ) ; }
}
--- OUTPUT ---
Static type I -> B::foo 2
Static type A -> A::foo
Static type B -> A::foo
c