if ( 拡張メソッド == インスタンスメソッド ) return ?
前の記事を書いてからやっと気付いたけど(^^;、これはつまりインスタンスメソッドの動作をまねてるんですね。
もうちょっと調べてみました。ToString() の例はイマイチなので、別の例に差し替えます。
using System; class Program { static void Main() { B b = new B { Val = 1 }; b.Foo(); // Object Ext.Foo( b ); // A //b.Baz(); // compile error! Ext.Baz( b ); // Ext.Baz( A ) Console.ReadKey(); } } static class Ext { public static void Foo( this object x ) { Console.WriteLine( "Object" ); } public static void Foo( this A x ) { Console.WriteLine( "A" ); } //public static void Foo( this B x ) { Console.WriteLine( "B" ); } public static void Baz( A x ) { Console.WriteLine( "Ext.Baz( A )" ); } } class A { public int Val; public void Baz() { Console.WriteLine( "A.Baz" ); } } class B { public int Val; public static implicit operator A( B b ) { return new A { Val = b.Val }; } }
b.Baz() だとコンパイルエラー。b が A 型に暗黙変換されないから。
Ext.Baz( b ) だと A 型に変換されるのでおっけい。
「引数」と「this になるもの」の変換規則は元々違ってた!
b.Baz() ってときの b の変換やその他の処理は「7.4.3 関数メンバの呼び出し」(MS の日本語仕様書の Ver1.2 を見てます)、7.3、7.5.5 ほか多数…。引数については「7.4.1 引数リスト」。やっぱり、それぞれ異なる変換規則があるようです。
「this になるもの」の変換規則は、前の記事で書いた拡張メソッドの1つめのパラメータの変換規則と同じようですね。正確なところはややこしすぎてわかりませんがw
結局、拡張メソッドがあらためてこの部分の変換規則の違いを浮き彫りにしたってのが正しいようです。そして拡張メソッドはこの違いをきちんと再現してるってことですね。でも、これヤヤコシイ。