4

このコードがあるとしましょう:

Action<int> gf = k => { };
Action<int> gfa = k => { k++; };

gf本文やステートメントがないことをどのように判断できますか?
内のステートメントの数を取得することは可能Actionですか?

GetNumberOfStatements(gf)which shouldに似たものreturn 0
または多分 HasEmptyBody(gf) べきreturn trueです;

4

3 に答える 3

1

.Net のデリゲートは、関数ポインターにすぎません。.Net メソッドに含まれる C# ステートメントの数がわからないのと同様に、.Net デリゲートに含まれるステートメントの数もわかりません。その理由の 1 つは、メソッドが必ずしも C# やステートメントの概念を持つ他の言語でコーディングされているとは限らないためです。オペコードベースのILに直接書き込むことができます

于 2013-04-04T14:18:06.210 に答える
0

編集:ビルドサーバーが再起動するのを待っている間に、これを少し修正することにしました...

私は実際に私の「ユーティリティライブラリ」の周りに何かを置いていますが、それはおそらくあなたを助けるかもしれません.

public static void DumpMethod(Delegate method)
{
    var mb = method.Method.GetMethodBody();
    var il = mb.GetILAsByteArray();
    var opCodes = typeof(System.Reflection.Emit.OpCodes)
        .GetFields()
        .Select(fi => (System.Reflection.Emit.OpCode)fi.GetValue(null));
    var mappedIL = il.Select(op => opCodes.FirstOrDefault(opCode => opCode.Value == op));
    var ilWalker = mappedIL.GetEnumerator();
    while(ilWalker.MoveNext())
    {
        var mappedOp = ilWalker.Current;
        if(mappedOp.OperandType != System.Reflection.Emit.OperandType.InlineNone)
        {
            var byteCount = 0;
            long operand = 0;
            switch(mappedOp.OperandType)
            {
                case System.Reflection.Emit.OperandType.InlineI:
                case System.Reflection.Emit.OperandType.InlineBrTarget:
                case System.Reflection.Emit.OperandType.InlineMethod:                
                case System.Reflection.Emit.OperandType.InlineField:
                case System.Reflection.Emit.OperandType.InlineSig:
                case System.Reflection.Emit.OperandType.InlineString:
                case System.Reflection.Emit.OperandType.InlineType:
                case System.Reflection.Emit.OperandType.InlineSwitch:
                    byteCount = 4;
                    break;
                case System.Reflection.Emit.OperandType.InlineI8:
                case System.Reflection.Emit.OperandType.InlineR:
                    byteCount = 8;
                    break;
            }
            for(int i=0; i < byteCount; i++)
            {
                ilWalker.MoveNext();
                operand |= ((long)ilWalker.Current.Value) << (8 * i);
            }
            Console.WriteLine("{0} {1}", mappedOp.Name, operand);                    
        }
        else
        {
            Console.WriteLine("{0}", mappedOp.Name);
        }
    }
}

テスト装置:

Func<int,int> addOne = i => i + 1;
DumpMethod(addOne);
Console.WriteLine();
Func<int,string> stuff = i =>
{
    var m = 10312;      
    var j = i + m;
    var k = j * j + i;
    var asStr = k.ToString();
    return asStr;
};
DumpMethod(stuff);

出力:

ldarg.0
ldc.i4.1
add
ret

ldc.i4 10312
stloc.0
ldarg.0
ldloc.0
add
stloc.1
ldloc.1
ldloc.1
mul
ldarg.0
add
stloc.2
ldloca.s 0
ldarg.0
call 167772167
stloc.3
ldloc.3
ret
于 2013-04-04T14:54:59.897 に答える