VB2005のMyClass.Method
某所より。
ところで、VB2005にある
MyClass.Hoge( );
というvirtual指定がされていても強制的に自分自身の
クラスのメソッドを呼び出す記法は、C#にはなかとですか?(´ω`)
それ以前に、VBが分かっていないので、VBのコードを理解するところからスタート。(^^;
Public Class Foo Public Overridable Function Method(x as Integer, y as Integer) as Integer Return x + y End Function Public Sub Test() Console.WriteLine (MyClass.Method(10, 20)) Console.WriteLine (Method(10, 20)) End Sub End Class Public Class Bar Inherits Foo Public Overrides Function Method(x as Integer, y as Integer) as Integer Return x * y End Function End Class Module App Sub Main() Dim bar as New Bar bar.Test () End Sub End Module ' 結果 ' 30 ' 200
このように仮想関数であっても、自分のクラスで定義されている実装を呼び出す機能のようです。では、具体的にどんなことが起きているのか、ILを覗いてみましょう。
.method public instance void Test() cil managed { // コード サイズ 31 (0x1f) .maxstack 8 IL_0000: ldarg.0 IL_0001: ldc.i4.s 10 IL_0003: ldc.i4.s 20 IL_0005: call instance int32 Foo::Method(int32, int32) IL_000a: call void [mscorlib]System.Console::WriteLine(int32) IL_000f: ldarg.0 IL_0010: ldc.i4.s 10 IL_0012: ldc.i4.s 20 IL_0014: callvirt instance int32 Foo::Method(int32, int32) IL_0019: call void [mscorlib]System.Console::WriteLine(int32) IL_001e: ret } // end of method Foo::Test
callで呼び出しているか、callvirtで呼び出しているかの違いだけのようですね。自分の知る限りだとC#ではサポートしていないと思います。個人的には仮想関数を無効にするような機能は混乱の元なので無くても良い気がします。
ただ、「C#で出来ない」というのは気に入らない(笑)ので無理矢理書いてみました。
using System; using System.Reflection; using System.Reflection.Emit; delegate R MethodDelegate<T,R>(object instance, T arg1, T arg2); public static class MethodCreator { static int n = 0; public static DynamicMethod Binary<T,R>(MethodInfo mi) { DynamicMethod dm = new DynamicMethod("tempMethod" + n++, typeof(R), new Type[] {typeof(object), typeof(T), typeof(T)}, mi.DeclaringType); ILGenerator il = dm.GetILGenerator(); if (mi.IsStatic) throw new ArgumentException(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, mi); il.Emit(OpCodes.Ret); return dm; } } public class Foo { static MethodDelegate<int,int> MyClassMethod; static Foo() { MethodInfo mi = typeof(Foo).GetMethod("Method"); DynamicMethod dm = MethodCreator.Binary<int,int>(mi); MyClassMethod = (MethodDelegate<int,int>)dm.CreateDelegate( typeof(MethodDelegate<int,int>)); } public virtual int Method(int x, int y) { return x + y; } public void Test() { // Foo.Methodを呼び出す Console.WriteLine (MyClassMethod(this, 10, 20)); Console.WriteLine (Method(10, 20)); } } public class Bar : Foo { public override int Method(int x, int y) { return x * y; } } public static class App { public static void Main() { new Bar().Test(); } } /* 結果 30 200 */
・・・いや、これはC#じゃないだろ・・・(^^;