Extension methods in C#


Overview 

Extension methods are a new feature for C# 3.0 and I had the opportunity to implement them in the Compiler. These methods can then be called with instance syntax on any object that is convertible(see convertibility section for details) to the first param of the method.

Validation  Extension methods are defined in C# as

static class Extensions

{

  public static IEnumerable<T> Where<T>(this IEnumerable<T> sequence, Predicate<T> predicate)

  {

     foreach (T item in sequence)

     {

        if (predicate(item))

        {

            yield return item;

        }

      }

   }

}

Several Interesting things to Note here

  1. The method is define in a top level static class ( the class is directly under the namespace)
  2. The method is static and decorates its first param with a new param modifier this, this param is called the “instance parameter” and its an error to use the “this” modifiers on any other parameter.
  3. No other parameter modifiers ( ref, out etc) are allowed with “this” (so values types can’t be passed by reference to an extension methods, VB will allow ref).
  4. The instance parameter can’t be a pointer type.
  5. The method is public (its accessible to anyone who can get to its parentclass).
  6. The Type parameter used must be defined on the method and not the parentclass.

5 & 6 are required because extension methods are bound as instance methods and the argument to instance parameter is the object on which the method is called. This means that the class in which the extension methods are defined is just a container to put the extension method in and will never be involved in binding it as an extension method e.g.

static class Extensions

{

   public static float Average(this System.Array array)

   {

       float average = 0;

       for (int I = 0; i < array.Length; i++)

       {

           average += (int)array.GetValue(i);

       }

       return average / array.Length;

   }

}

is bound as

int[] array = {34, 56, 100, 45, 23, 12};

array.Average(); note  Extensions has nothing to do with the call

 

      7.  The instance parameter cannot have the type of the Type parameter.

       As this would make the impossible to bind the method as an instance method  e.g.

public static class Extension3

{

    public static class Extension4

    {

        public static void Foo<T>(this T inst) { }

    }

}

Convertibility

The following conversion are defined on instance parameter on Extension methods

  1. Identity conversion (type S is S)
  2. Implicit reference conversions
  3. Boxing Conversions

Finding Extension methods

So how is the compiler to know which extension method to bind? The compiler looks for extension methods in the innermost namespace when the call is made for extension methods and then in all the namespaces imported by the “using” clause. This process is followed moving outward until we reach the topmost namespace.

Since extension methods can be imported in to the current context by the “using” clause and bound to any object which is assignable(see convertibility section for details) to the instance parameter, all sorts of interesting possibilities open up for extending the methods implemented by a type. This can simply be done by importing a library of extension methods and using these methods as if they were declared on a type that you don’t own. This means that

1. Depending on the library you import the code can be made to do different things.

2. The client gets an interesting way to extend a type that he does not own.

Delegates

Calling methods is all well and good, but do extension methods work when instantiating a delegates?

Of course they do, (here is a good use of curried delegates). If you are not sure what curried delegates ( yum yum Indian food ) are and how to the compiler uses them. Don’t be alarmed, i will be covering that in the next post of Extension method binding. 

e.g. using the Where extension defined above

double[] array = {34,45,67.12,95,25,69};

Func<Func<double, bool>, IEnumerable<double>> fun = array.Where<double>;

fun(new Func<double, bool>(Pred));

 

public static bool Pred(double arg)

{

   if (arg > 10)

       return true;

   return false;

}

This works just as long as the instance param is a reference type πŸ™‚  (No Curry for you, Value Type)  

Extension methods can also be called on Delegate e.g.

public delegate T del1<T>(T val);

 

And Extension method  Exec defined as

static class Extension

 {

     public static T Exec<T>(this del1<T> source, T param)

     {

         return source(param);

     }

}

 

We can write client code like 

 

public class Test
{
    public static void Main()
    {
           Test t = new Test();
           del1<int> d1 = t.func<int>;
           d1.Exec(100);
     }

    public T func<T>(T val)
    {
           return val;
     }

}

 

This ends the first post on extension methods, next how exactly extension methods are bound.

kick it on DotNetKicks.com

 

Comments (18)

  1. Wilka says:

    When you say "6. The Type parameter used must be defined on the method and not the parentclass." what do you mean by "Type parameter"? I’m not sure which parameter this refers to, is it the type of the instance parameter? or some other parameter?

  2. Dave says:

    That method is generic so it has a type parameter list (the names between < and > are the type parameters). So when he says "the Type parameter" he is referring to the T.

    You can also make generic classes, that’s when the class itself has a type parameter list. Number six is saying that with extension methods you can’t use any type parameters from the containing class only type params from the (generic) extension method.

  3. Rob P says:

    There’s no way to add static methods or new operators using Extension Methods is there?

  4. Sree_C says:

    All Extension methods are static methods and can be called as such.

    No extension methods can’t be operator they are always bound as methods. Object.ExtensionName(arguments …. )

  5. Rob P says:

    Sure the extension methods themselves are static methods, but they appear as instance methods on the type being extended.

    Is there a technical reason why you couldn’t extend types with new static methods (and operators) or was this just a design decision to support the minimal amount necessary to make LINQ work nicely?

  6. Sree_C says:

    Extension methods were added so that we can call the methods with instance syntax. This is usefull to write code that reads more like the intent of the programmer. Making the code more comprehensible and easy to change and maintain.

    So we can write

    order.Search((o) => o.Name = custName).SendTobilling();

    It is important note that this is just a change in the binding rules for instance methods and is suported by intellisence and debugging which use the compilers binding code.

    Similar changes to binding rules for operators would be a breaking change for exiting code,  and would make the client code confusing since  a + b would work where the extensions were imported and not every where else. Also relational operators can only be overloaded in pairs ( OOo my head is hurting with the possible validation checks for this one and we are only getting started). Combine this with the fact that completion lists would be of no help to you, all in all this is solvable but very problematic.

    Static methods … well since extension methods are static to begin with does it matter which type you are calling the method on (Extesnsion type of your type).

  7. You’ve been kicked (a good thing) – Trackback from DotNetKicks.com

  8. I open a codeplex project for an Extension Methods library : http://www.codeplex.com/ExtensionMethods

  9. Welcome to the 27th Community Convergence. I use this column to keep you informed of events in the C#

  10. Arshvinder Singh says:

    Plz expalin me from where this thing came from

    We can write client code like

    del1<int> d1 = t.func<int>;

  11. Sree_C says:

    Sorry for the incomplete example … basically we are creating an delegate and calling the extension method Exec on it. The important information missing is the defintion of the method func that created the delegate.

     public class Test

     {

        public static void Main()

        {

            Test t = new Test();

            del1<int> d1 = t.func<int>;

            Console.WriteLine(d1.Exec(100));

        }

        public int func()

        {

           return 10;

        }

        public T func<T>(T val)

        {

            return val;

        }

    }

  12. ftorres says:

    We started using some of the new C# 3.0

    features with our functional web testing tool InCisif.net, including extensions methods and lambda expression.

    Our goal is to be able to simplify the test code.

    And it is great.

    see our posts :

    http://blog.incisif.net/2007/09/02/incisifnet-20-and-c-30-lambda-expression.aspx

    http://blog.incisif.net/2007/05/28/orcas-net-35-and-c-30.aspx

    Feedback welcome.

  13. re: 拑弡パソッドγͺら、this == null でもいい。

  14. avantika srivastava says:

    hi

    can you plaese explain me, how can we add images using the extension methods………

  15. Sree_C says:

    avantika, i am not sure i understand. Extension methods add a usefull call symatics, its up the user to implement whatever they want in the method body.

  16. JDP says:

    Thanks for the thorough description. Just what I was looking for.

  17. Marty says:

    Hello,

    today I have tried to add some methods mathematical notation to my classes to work on voxel volume data. I wanted to implement an operator * which works on the volume.

    Is it possible to use extension methods to add some operator functions?