Tôi cố gắng xây dựng một đuôi đệ quy Expression
trong .NET 4.0.Tôi có thể xây dựng một cuộc gọi đuôi được gọi là biểu thức tối ưu đệ quy không?
Tôi có thể xây dựng nó nhưng, phương pháp được biên dịch này không được tối ưu hóa cuộc gọi đuôi, mặc dù chỉ định tailCall = true
, IL được tạo không có hướng dẫn tiền tố tail.
.
Vui lòng cho tôi biết cách tạo một cuộc gọi đuôi được tối ưu hóa đệ quy Expression
?
Biểu thức xây dựng bên dưới.
using System;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
public delegate int RecursiveFunc(RecursiveFunc function, int acc, int n);
internal class Program
{
private static void Main()
{
var funcParam = Expression.Parameter(typeof (RecursiveFunc));
var accParam = Expression.Parameter(typeof (int));
var nParam = Expression.Parameter(typeof (int));
var constZero = Expression.Constant(0, typeof (int));
var accumExpr = Expression.Add(accParam, nParam);
var decrimentExpr = Expression.Decrement(nParam);
var invokeExpr = Expression.Invoke(funcParam, funcParam,
accumExpr, decrimentExpr);
var testExpr = Expression.Equal(nParam, constZero);
var condExpr = Expression.Condition(testExpr, accParam,
invokeExpr);
var lambda = Expression.Lambda<RecursiveFunc>(condExpr,
"TailCall", true, new[] {funcParam, accParam, nParam});
var sumParam = Expression.Parameter(typeof (RecursiveFunc),
"Sum");
var method = lambda.Compile();
var ans = method(method, 0, 100);
Console.WriteLine(ans);
}
}
}
Và expresion lambda này tạo ra IL dưới
.method public static int32 EvaluateTarget (
class [ConsoleApplication2]ConsoleApplication2.RecursiveFunc '',
int32 '',
int32 ''
) cil managed
{
// Method begins at RVA 0x2050
// Code size 25 (0x19)
.maxstack 7
IL_0000: ldarg.2
IL_0001: ldc.i4.0
IL_0002: ceq
IL_0004: brfalse IL_000b
IL_0009: ldarg.1
IL_000a: ret
IL_000b: ldarg.0
IL_000c: ldarg.0
IL_000d: ldarg.1
IL_000e: ldarg.2
IL_000f: add
IL_0010: ldarg.2
IL_0011: ldc.i4.1
IL_0012: sub
IL_0013: callvirt instance int32
[ConsoleApplication2]ConsoleApplication2.RecursiveFunc::Invoke(class
[ConsoleApplication2]ConsoleApplication2.RecursiveFunc, int32, int32)
IL_0018: ret
} // end of method AutoGeneratedType::EvaluateTarget
Bạn nên đăng một số mã mà bạn đang sử dụng để tạo ra các biểu hiện. Thật khó để nói chắc chắn. – casperOne
Cảm ơn lời khuyên của bạn. Và tôi thêm một mã mẫu và biểu thức này được tạo ra IL –