関数の呼び出し方
関数はどうやって実行できるのか調べてみた
前にも調べたような気がするけど、忘れたのでもう一回
C#でInt->String->Intの関数を呼ぶ場合
delegate int F_dele(String s); static int f(String s) {return(999);} var x = new F_dele(f); Console.Write(x("Hoge"));
C#様に任せると大体こうなる
staticな関数だとF_dele.ctorの第一引数はldnullらしい
ldnull ldftn int32 f(string) newobj instance void F_dele.ctor(object, native int) stloc x ldloc x ldstr "Hoge" callvirt instance int32 F_dele::Invoke(string) call void Console::WriteLine(int32)
delegateはMulticastDelegateを継承したクラスになるが、正直よくわかんない
呼び出したい型ごとにクラス作って、ldftnした結果をいれるのはじゃんくさい
ldftnした結果の型を管理を自分でやるならこれで十分
ldftn int32 f(string) stloc x ldstr "Hoge" ldloc x calli int32 (string) call void Console::WriteLine(int32)
delegate int F_dele(String s); virtual int f(String s) {return(999);} var self = new Self(); var x = new F_dele(self.f); Console.Write(x("Hoge"));
メソッドだとF_dele.ctorの第一引数はレシーバっぽい
virtualじゃないメソッドなら当然ldftnになる
newobj Self::.ctor stloc self ldloc self ldvirtftn int32 f(string) newobj instance void F_dele.ctor(object, native int) stloc x ldloc x ldstr "Hoge" callvirt instance int32 F_dele::Invoke(string) call void Console::WriteLine(int32)
メソッドをldftnするとcalliの第一引数をレシーバにせんとならん
ってことはILに落とす前にこれは関数orメソッドだかんねと言う情報をもたせんとならん
ついでにメソッドを高階関数にすんのがめんどい
そのせいかldftnをdelegateでラップして渡すのがC#様やVB様のやり方くさい
デリゲートなら定義するときにldftn/ldvirtftnを切り替えてレシーバ渡すだけになる
関数を呼ぶところはcallvirtに統一できる