ILの call と callvirt の違い
当面ILとC#と.NETな記録。インサイドかもしれないし、ダークサイドかもしれない実験記です。
実験1
ILの call と callvirt の違いがよくわからないのにプロパティを読もうってのがそもそもの間違いだなと思って、比較するコードを書いてみました。
よくある継承のサンプルコードでC#のコール、ILのcall、callvirtを比較。
using System; using System.Reflection.Emit; class Base { public virtual void Say() { Console.WriteLine( "Base (" + this.GetType() + ")" ); } } class Derived : Base { public override void Say() { Console.WriteLine( "Derived (" + this.GetType() + ")" ); } } class Class3 { static void Main() { Base b = new Base(), d = new Derived(); Console.WriteLine( " b.Say():" ); b.Say(); Console.WriteLine( "\n d.Say():" ); d.Say(); Console.WriteLine( "\n CallSay( b ):" ); CallSay( b ); Console.WriteLine( "\n CallSay( d ):" ); CallSay( d ); Console.WriteLine( "\n CallvirtSay( b ):" ); CallvirtSay( b ); Console.WriteLine( "\n CallvirtSay( d ):" ); CallvirtSay( d ); Console.ReadKey(); } delegate void Call( Base b ); static void CallSay( Base b ) { DynamicMethod dm = new DynamicMethod( "", null, new Type[] { typeof( Base ) }, typeof( Class3 ) ); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit( OpCodes.Ldarg_0 ); ilgen.Emit( OpCodes.Call, b.GetType().GetMethod( "Say" ) ); ilgen.Emit( OpCodes.Ret ); Call callSay = ( Call ) dm.CreateDelegate( typeof( Call ) ); callSay( b ); } static void CallvirtSay( Base b ) { DynamicMethod dm = new DynamicMethod( "", null, new Type[] { typeof( Base ) }, typeof( Class3 ) ); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit( OpCodes.Ldarg_0 ); ilgen.Emit( OpCodes.Callvirt, b.GetType().GetMethod( "Say" ) ); ilgen.Emit( OpCodes.Ret ); Call callvirtSay = ( Call ) dm.CreateDelegate( typeof( Call ) ); callvirtSay( b ); } }
結果は…
b.Say(): Base (Base) d.Say(): Derived (Derived) CallSay( b ): Base (Base) CallSay( d ): Derived (Derived) CallvirtSay( b ): Base (Base) CallvirtSay( d ): Derived (Derived)
あれ、そのまんま。
つづく
リフレクションのパフォーマンス
同じ筆者によるリフレクションのパフォーマンスの記事。
http://www.microsoft.com/japan/msdn/msdnmag/issues/05/07/Reflection/default.aspx
リフレクションの何が遅くて何が遅くないのか、また、どうすれば速くできるのかといったあたり。ただし、.NET2.0のプレリリースバージョンに基づいているそうで、参考程度か。インターフェイスよりデリゲートが遅いことになってが、これは逆転したハズ。