拡張メソッドの字面が引き起こす混乱

こちらは変換規則なんてややこしい問題ではないけど、字面が引き起こす混乱の例。

using System;

class P
{
  static void Main()
  {
    S a = new S { Val = 0 };
    Console.WriteLine( a.Val ); // 0

    a.Inc();
    Console.WriteLine( a.Val ); // 1

    a.ExtInc();
    Console.WriteLine( a.Val ); // 1

    Ext2.ExtInc( a );
    Console.WriteLine( a.Val ); // 1

    a = a.ExtInc2();
    Console.WriteLine( a.Val ); // 2

    a = Ext2.ExtInc2( a );
    Console.WriteLine( a.Val ); // 3

    Console.WriteLine();


    C c = new C { Val = 0 };
    Console.WriteLine( c.Val ); // 0

    c.Inc();
    Console.WriteLine( c.Val ); // 1

    c.ExtInc();
    Console.WriteLine( c.Val ); // 2

    Ext2.ExtInc( c );
    Console.WriteLine( c.Val ); // 3

    c = c.ExtInc2();
    Console.WriteLine( c.Val ); // 4

    c = Ext2.ExtInc2( c );
    Console.WriteLine( c.Val ); // 5

    Console.ReadKey();
  }
}

struct S
{
  public int Val;
  public void Inc() { this.Val++; }
}

class C
{
  public int Val;
  public void Inc() { this.Val++; }
}

static class Ext2
{
  public static void ExtInc( this S a ) { a.Val++; }
  public static S ExtInc2( this S a ) { a.Val++; return a; }

  public static void ExtInc( this C a ) { a.Val++; }
  public static C ExtInc2( this C a ) { a.Val++; return a; }
}

値型を引数に取って値を変更する拡張メソッドは、イヤラシイ。
説明不要ですよね。え、なんで?と思ってしまった方は、一息ついてから考えればアハ体験できるハズ。