Skip to content

Your basic friends are polymorphism and inheritance

There are many programming patterns, which you learn hands-on.

BONUS

If you landed here with already substantial knowledge, revise your JavaScript patterns here.

And now some C# time.

cs
class Program {
    public class Base {
        public virtual void Foo(int x) { Console.WriteLine("Base"); }
    }
    public class Derived : Base {
        public override void Foo(int x) { Console.WriteLine("Derived overridden"); }
        public void Foo(object x) { Console.WriteLine("Derived object"); }
    }
    static void Main(string[] args) {
        var a = new Derived();

        a.Foo(1);
        var b = (Base)a;
        b.Foo(1);

        Console.ReadLine();
    }
}

The output is: "Derived object, Derived overridden"

The main idea here is that the program first looks not for matching types, but for appropriate types in a type hierarchy, where naturally "object" is at the top.

Secondly, all virtual methods are only called when an instance of this class is created and accessed, and not, for example, an instance of a derived class (using typing to the type of the base class). Additionally, the code from a base class can be executed by

base.<Function>();

The "override" statement indicates that a method is pointer-independent, i.e., it is used by a derived class. (If we remove "override" from the example, we get an "object, base" output).

Thirdly,

var b = (Base)a;

creates a new instance (type "Base"), but the memory allocation points to the Foo method overridden by class Derived, so calling Foo(object x) is not permissible, moreover, we access the overridden Foo(int x).

A small change that can help you understand it better:

cs
class Program {
    public class Base {
        public virtual void Foo(B x) { Console.WriteLine("Base B"); }
        public virtual void Foo(C x) { Console.WriteLine("Base C"); }
    }
    public class Derived : Base {
        public void Foo(A x) { Console.WriteLine("Derived A"); }
        public override void Foo(B x) { Console.WriteLine("Derived overridden B"); }
        public override void Foo(C x) { Console.WriteLine("Derived overridden C"); }
    }

    static void Main(string[] args) {
        int x = 1; A y = new A(); B z = new B(); C zz = new C();

        var a = new Derived(); a.Foo(z); a.Foo(zz); ((Base)a).Foo(z);

        Console.ReadLine();
    }

    public class A { int a; }
    public class B : A { int b; }
    public class C : B { int c; }
}

The output is: Derived A, Derived A, Derived overridden B.

And if the function public void Foo(A x) is commented out:

Derived overridden B, Derived overridden C, Derived overridden B.

So first, it looks for a match between non-overridden methods: A for z and zz.

If two functions were defined with "object" or "A" as parameters, only Foo(A x) would be executed.

Enjoy!

Automate, Integrate, Build and Inform. Amathron Solutions℠, Amathron Assistant™, Armvolt™