Extension methods (advanced)

Overriding methods is old-fashioned, well-known and broadly used.

Since .NET 4.0 extension methods were added. You can now easily add new capabilities to existing types like classes, structs or interfaces.
Extension methods are defined as static methods but are called by using instance method syntax, their scope is their namespace. You have to explicitly import the namespace with a using directive unless you are in the right namespace already.

First of all you need to generate a static class, which is neither generic nor nested. Then use the this keyword on the first parameter of a static method.

namespace WeAreInTheSameNamespace {
    public static class ExtendingExistingTypes {

        public static double DoSomething(this double x, double y, int z) {
            return x * y * z;
        } //        

    } // class

    public static class ExtendingExistingTypesTest {
        public static void Test() {
            double x = 5.0;
            double r;
            r = x.DoSomething(4.0, 2); // static method called like an instance
            Console.WriteLine(r);   // = 40

            r = ExtendingExistingTypes.DoSomething(6.0, 7.0, 1);
            Console.WriteLine(r);   // = 42

            Console.ReadLine();
        } //
    } ///
} // namespace

Did you realize the this keyword in public static double DoSomething(this double x, double y, int z) {}? It tells the compiler:

  • If someone uses the method DoSomething() as a standard static method, simply ignore the this keyword.
  • If the method is used like an instance method, then the first parameter is the instance itself. The second parameter becomes the first parameter.

Therefore we only have 2 parameters in the first method call [r = x.DoSomething(4.0, 2);] and 3 parameters in the second method call [r = ExtendingExistingTypes.DoSomething(6.0, 7.0, 1);].
The this keyword defines the type it is extending.

Have you seen such before? Sure, the most common extension methods are defined in interface IEnumerable. You probably just haven’t looked at them this way.

public static void Test2() {
    IEnumerable<double> lList = new double[] { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
    double d = lList.Average();  // extension method of an interface

    Console.WriteLine(d);
    Console.ReadLine();
} //

To avoid trouble you should be aware that extension methods have a lower priority than existing method signatures. Trying to override an existing method signature in an interface, struct or class is nonsense and will, due to its lower priority, never be called!

Extension methods are very useful when you cannot change the source code (eg. you don’t have the code of a library), but want to associate a new method with eg. the existing class without using override.

namespace NMyInterface {
    public interface IMyInterface {
        void MethodB();
    } // interface
} // namespace

// Define extension methods for IMyInterface. 
namespace NCoolExtensions {
    using NMyInterface;

    public static class MyExtension {
        public static void MethodA(this IMyInterface x, double d) { Console.WriteLine("Extension MethodA, double"); }
        public static void MethodA(this IMyInterface x, int i) { Console.WriteLine("Extension Method A, int"); }

        // Nonsense signature, the method will never be called because of its lower priority.
        public static void MethodB(this IMyInterface x) { Console.WriteLine("Extension nonsense"); }
    } // class
} // namespace

namespace NTestArea {
    using NCoolExtensions;
    using NMyInterface;

    class A : IMyInterface {
        public void MethodB() { Console.WriteLine("MethodB"); }
    } // class

    class B : IMyInterface {
        public void MethodA(int i) { Console.WriteLine("MethodA"); }
        public void MethodB() { Console.WriteLine("MethodB"); }
    } // class

    class C : IMyInterface {
        public void MethodA(object o) { Console.WriteLine("MethodA"); }
        public void MethodB() { Console.WriteLine("MethodB"); }
    } // class

    class D {
        public static void Test3() {
            Console.WriteLine("Class A");
            A a = new A();
            a.MethodA(2);
            a.MethodA(2.0);
            a.MethodB();

            Console.WriteLine("Class B");
            B b = new B();
            b.MethodA(2);
            b.MethodA(2.0);
            b.MethodB();

            Console.WriteLine("Class C");
            C c = new C();
            c.MethodA(2);
            c.MethodA(2.0);
            c.MethodA(new object());
            c.MethodB();
        } //
    } // class
} // namespace

example output:
Class A
Extension Method A, int
Extension MethodA, double
MethodB
Class B
MethodA
Extension MethodA, double
MethodB
Class C
MethodA
MethodA
MethodA
MethodB

Have a look at the output of Class C. MethodA(object o) hides all extension methods. Be cautious!

Advertisements

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on January 6, 2014, in Advanced, C#, Interfaces and tagged , , , , , . Bookmark the permalink. 3 Comments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: