Zurück

Late Binding and Polymorphism in C#


Late binding

The decision to which version of the method to invoke cannot be made at compile time. That decision must be deferred and made at runtime. This is sometimes referred to as late binding.

Example

using System;
using System.Collections;
using System.Text;

namespace VirtualMethods
{
    public class MyControl
    {
        // These members are protected and thus visible
        // to derived class methods. We'll examine this
        // later in the chapter

        protected int top;
        protected int left;

        // Constructor takes two integers to
        // fix location on the console

        public MyControl(int top, int left)
        {
            this.top = top;
            this.left = left;
        }

        // Simulates drawing the window
        public virtual void DrawWindow()
        {
            Console.WriteLine("MyControl: drawing Control at {0}, {1}",
            top, left);
        }
    }

    // ListBox derives from MyControl
    public class ListBox : MyControl
    {
        // Fields
        private string listBoxContents;

        // Constructor adds a parameter
        public ListBox(
            int top,
            int left,
            string contents): base(top, left)  // Call base constructor
        {
            listBoxContents = contents;
        }
  
        // An overridden version (note keyword) because in the
        // derived method we change the behavior

        public override void DrawWindow()
        {
            base.DrawWindow();  // Invoke the base method
            Console.WriteLine("Writing string to the listbox:
           {0}",listBoxContents);
        }
    }

    // Button derives from MyControl
    public class Button : MyControl
    {
        public Button(
            int top,
            int left): base(top, left)
        {
            // Empty Body
        }

        // An overridden version (note keyword) because in the
        // derived method we change the behavior

        public override void DrawWindow()
        {
            Console.WriteLine("Drawing a button at {0}, {1}\n", top, left);
        }
    }

    // Test Class
    public class Tester
    {
        static void Main()
        {
            // Static Binding at Compile Time
            MyControl win = new MyControl(1, 2);
            ListBox lb = new ListBox(3, 4, "Stand alone list box");
            Button b = new Button(5, 6);
            win.DrawWindow();
            lb.DrawWindow();
            b.DrawWindow();

            // Dynamic Binding at Run Time, create an Array
            // holding the References to the Controls

            MyControl[] winArray = new MyControl[3];
            winArray[0] = new MyControl(1, 2);
            winArray[1] = new ListBox(3, 4, "List box in array");
            winArray[2] = new Button(5, 6);

            // The correct DrawWindow() is called = Late Binding
            for (int i = 0; i < 3; i++)
            {
                winArray[i].DrawWindow();
            }

        }
    }
}

The compiler now knows to use the overridden method when treating these objects polymorphically. The compiler is responsible for tracking the real type of the object and for handling the «late binding» so that it is ListBox.DrawWindow() that is called when the Control reference really points to a ListBox object.