属性System.Runtime.CompilerServices.MethodImplAttribute
を使用すると、装飾されたメソッドの処理方法に関するヒントをJITコンパイラに与えることができます。特に、オプションMethodImplOptions.AggressiveInlining
は、可能であれば、影響を受けるメソッドをインライン化するようにコンパイラに指示します。残念ながら、F#コンパイラは、ILを生成するときにこの属性を単に無視するようです。MethodImplOptions.AggressiveInliningをF#関数に適用する
例:次のC#コード
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Inc(int x) => x + 1;
は
.method public hidebysig static int32 Inc(int32 x) cil managed aggressiveinlining
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: add
IL_0003: ret
}
注 "aggressiveinlining" フラグに変換されます。
このF#コードは、しかし
[<MethodImpl(MethodImplOptions.AggressiveInlining)>]
let inc x = x + 1
.method public static int32 inc(int32 x) cil managed
{
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
いいえ "aggressiveinlining" になります。私はまた、適切なクラスの静的メソッドと非静的メソッドに属性を適用しようとしましたが(type ...
)、結果は同じです。
私は」と同等であるかどうかはわからないけれどもそう
type Dummy =
member self.Item
with [<MethodImpl(MethodImplOptions.AggressiveInlining)>] get x = x + 1
結果ILは...
.method public hidebysig specialname instance int32 get_Item(int32 x) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.MethodImplAttribute::.ctor(valuetype [mscorlib]System.Runtime.CompilerServices.MethodImplOptions) = (01 00 00 01 00 00 00 00)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ret
}
あるようにしかし、私は、カスタムインデクサにそれを適用した場合C#コンパイラによって生成された "aggressiveinling"フラグを返します。
この動作は望ましく、予想されますか? F#コンパイラのバグですか?
(注:私はF#のinline
キーワードを認識してんだけど、それが唯一の私のライブラリではなく、C#の消費者のF#のクライアントのために動作します。)
AFAIKこの属性は、JITによって使用されます。このメソッドは、インライン化する必要があることを示します。それが正しい場合は、マシンコードを生成する必要があります。注意; JITを実行しているデバッガと同じように、.NETで逆アセンブリを表示するのと同じくらい簡単ではありません。erはあまり攻撃的ではありません。 – FuleSnabel
ああ、私はあなたが意味するものを参照してください。 ILメタデータには欠けているようです。後でこれをチェックさせてください。 – FuleSnabel
'PreserveSig'、' Synchronized'、 'NoInlining'だけが尊重されているようです - [IlxGen.fs]の' ComputeMethodImplAttribs'(https://github.com/Microsoft/visualfsharp/blob/master/src/fsharp)を参照してください。 /IlxGen.fs) – kvb