Common Type System—Virtuals and Overriding


Jump to: navigation, search
Visual C# Tutorials
.NET Framework Tutorials

Common Type System

© 2006 Wiley Publishing Inc.

Virtuals and Overriding

By default, subclasses inherit both nonprivate method interfaces and implementations of their base classes (all the way up the chain). A method can be marked as virtual, however, which declares that further derived types can override the behavior of the base type. Overriding a virtual method simply replaces the implementation inherited from the base type.

Some languages like Java treat all methods as virtual by default. C# does not, meaning that you must opt in to virtualism explicitly using the virtual keyword.

class Base
{
   public virtual void Foo()
   {
      Console.WriteLine(“Base::Foo);
   }
}
 
class Derived : Base
{
   public override void Foo()
   {
      Console.WriteLine(“Derived::Foo);
   }
}

Derived has overridden the method Foo, supplying its own implementation. When a call is made to the virtual method Base::Foo, the method implementation is selected at runtime based on the identity the instance against which the call is made. For example, consider the following sample:

// Construct a bunch of instances:
Base base = new Base();
Derived derived = new Derived();
Base derivedTypedAsBase = new Derived();
 
// Now invoke Foo on each of them:
base.Foo();
derived.Foo();
derivedTypedAsBase.Foo();

When run, the above snippet of code will output the following to the console:

Base::Foo
Derived::Foo
Derived::Foo

To demonstrate that no analysis trickery accomplishes this, consider this method:

public void DoSomething(Base b) { b.Foo(); }
 
// In another assembly altogether...
DoSomething(new Base());
DoSomething(new Derived());

This prints out the following:

Base::Foo
Derived::Foo

Virtual method dispatch traverses the object reference to get at the method table of the instance. (We described object layout earlier in this chapter; if you’ve forgotten, you might want to refer back.) The method table contains a set of method slots, each of which is a pointer to a piece of code. When performing a virtual method dispatch, the pointer to the object is dereferenced, and then the pointer to the appropriate virtual method slot in the method table; then the value held in the slot is used as the target address of the method call. Please refer to Chapter 3 for more information about virtual method dispatching, in particular how the JIT Compiler plays a role.


Previous_Page_.gif Next_Page_.gif





Personal tools