using System; public class A { public int x = 0; public virtual void f() { Console.WriteLine("A.f"); } } public class B : A { public override void f() { Console.WriteLine("B.f"); } } public static class extensions { // an "extension method that appears to add a new method to class A: public static void g(this A n) { Console.WriteLine("A.g extension"); } public static void g(this B n) // does this "override" the other g? NO. { Console.WriteLine("B.g, did override work?"); } public static void Main(string[] av) { A m = new A(); m.g(); // calls the newly added method. A n = new B(); n.g(); // which will this call? This will print A.g extension. // THERE'S NO DYNAMIC DISPATCH HERE. n.f(); // doesn't work like this! dynamic dn = n; ((B)dn).g(); // "works", but need cast to B, hardly dynamic } }//extensions /* Extension methods turn out to be yet another "feature" of C# that only allows programmers to use a slightly different syntax: n.g() instead of g(n). They offer nothing new to the following kind of static definition in Java: public static void g(A n) { System.out.println("g(A)"); } public static void g(B n) { System.out.println("g(B)"); } The choice of which g is called is based on the STATIC type of its argument, and there is no dynamic dispatch. Java language designers did consider adding more agreesive extension methods that do allow dynamic dispatch, but rejected it because it violates certain traditional beliefs concerning abstraction in programming. Extension methods are easy to do in untyped languages: in perl, objects are often represented with hash tables, and it's always possible to add another entry to the table. Extention are generally not supported in languages (Java, C#, Swift, Kotlin, even C++) that contain a notion of a typed interface or protocol. "Implementing an interface" implies a kind of 2-way contract: no more or less should be done. */