Conversion rules for Instance parameters and their impact

Overview: Instance parameter is the first parameter of an extension method and has the "this" parameter modifier. I discuss special conversion rules for them and some of the things that users of extension methods might encounter.

Consider the code bellow

using System;
using System.Linq;

namespace TestExtensions
{
    class Program
    {
        static void Main()
        {
            0.Foo();    // 1
            0f.Foo();
            0d.Foo();

            A.Foo(0);   // 2
            A.Foo(0f);
            A.Foo(0d);
        }
    }

    public static class A
    {
        public static void Foo(this long x) { Console.WriteLine("Long"); }
        //public static void Foo(this int x) { Console.WriteLine("int"); }
        public static void Foo(this object x) { Console.WriteLine("Object"); }
        public static void Foo(this double x) { Console.WriteLine("decimal"); }
        public static void Foo(this float x) { Console.WriteLine("float"); }
        public static void Foo(this short x) { Console.WriteLine("short"); }
    }
}

1 binds to Foo(object) and 2 binds to Foo(short). This means that the same method when used as an extension method binds to a different overload than if used as an static method.

That raise the question Why is that ?

This is so because the conversions rules for instance parameter in an Extension methods are

  1. Identity conversions
  2. Implicit reference conversions
  3. Boxing conversions

So we are not considering numeric conversions and this can cause some confusion. 0 is of type int and will not be implicitly converted to long while binding the method as an Extension Method.

Extension methods have different semantics than standard static methods, since they are called by the client as an instance method. So the conversion rules are modified so that they behave as such.

Lets say we define an instance method on int does it mean I can call it on a object of type long ? It is this kind of enforcement that the conversion rules enforce.

uncommenting the perfect match Foo(this int x) and they behave the same ...