I have found little issue with expression trees and would like to know whether such is a bug or a feature. I have this code. The first function assigns one to a variable and returns it.
static class Functions
{
static public Expression<Func<int>> GetOne()
{
//Returns something like this () => {int x; return x +1;}
var variable = Expression.Variable(typeof(int));
var f = Expression.Lambda<Func<int>>(
Expression.Block(
new[] { variable },
Expression.Assign(variable, Expression.Add(variable, Expression.Constant(1)))
));
return f;
}
static public Expression<Func<int>> ApplyTenTimes()
{
var i = Expression.Variable(typeof(int));
var breakLabel = Expression.Label();
var f = GetOne();
var loop = Expression.Lambda<Func<int>>(
Expression.Block(
new[] { i },
Expression.Block(
new Expression[] {
Expression.Loop(Expression.Block(
Expression.IfThen(Expression.Equal(i, Expression.Constant(10)), Expression.Break(breakLabel)),
Expression.PostIncrementAssign(i),
Expression.Call(typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }), Expression.Call( Expression.Invoke(f),typeof(int).GetMethod("ToString", new Type[0]))
))),
Expression.Label(breakLabel),
Expression.Invoke(f)
})));
return loop;
}
}
f = Functions.GetOne().Compile();
IEnumerable<int> a = Enumerable.Range(0, 9).Select(_ => f()).ToList();
//Prints 1
Console.WriteLine(f());
f = Functions.ApplyTenTimes().Compile();
//Prints 1, ..., 10, 1
Console.WriteLine(f());
I expected the f always prints 1 as 0 is a default value for int.
If you try to get an interpreted delegate when calling Compile:
var f = Functions.ApplyTenTimes().Compile(preferInterpretation: true);
Console.WriteLine(f());
Then it behaves as you'd expect - "1" is printed eleven times.
Based on this fact, this is highly likely to be a bug in the expression compiler when compiling a loop expression, since the delegate should have the same behaviour regardless of whether it is interpreted or compiled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With