我想将
Expression
实例重用于另一个 Expression
建筑,如下面的代码所示。安全吗?有没有什么陷阱?
using System.Linq.Expressions;
class Program
{
static void Main()
{
ParameterExpression x = Expression.Parameter(typeof(int), "x");
ParameterExpression y = Expression.Parameter(typeof(int), "y");
// Reuse x and y parameter expressions
BinaryExpression sum = Expression.Add(x, y);
BinaryExpression mutiply = Expression.Multiply(x, y);
// Reuse multiply and sum expressions
BinaryExpression foo = Expression.Subtract(mutiply, sum); // xy - (x + y)
Func<int, int, int> sumFunc = Expression.Lambda<Func<int, int, int>>(sum, x, y).Compile();
Func<int, int, int> multiplyFunc = Expression.Lambda<Func<int, int, int>>(mutiply, x, y).Compile();
Func<int, int, int> fooFunc = Expression.Lambda<Func<int, int, int>>(foo, x, y).Compile();
Console.WriteLine(sumFunc(3, 2));
Console.WriteLine(multiplyFunc(3, 2));
Console.WriteLine(fooFunc(3, 2));
}
}
您可以安全地重复使用表达式。
表达式树是不可变的,因此您无需担心使用
sum
的人修改 LHS 和 RHS 表达式,导致使用 multiply
的人也(意外地)看到更改。当然,如果您故意在节点中放置一些可变的东西(例如 List<T>
),则可能会发生类似上述的情况。但这并不是 Expression
的问题。
Expression
是引用类型,因此重用与不重用的唯一区别是某些树节点对子节点具有相同的引用。例如,在您的代码中,object.ReferenceEquals(sum.Left, multiply.Left)
将为 true。如果你没有重复使用x
,那就是假的。也就是说,很难想象表达式树的任何用例取决于两个节点是否是相同的引用。大多数使用表达式树的 API 只查看节点的类型以及其中的值。