我有一个实现Sequence
的{{1}}类型。 ISequence
实现ISequence
,其中IEnumerable<Element>
是另一种自定义类型。目前,我的Element
类型将用于生成序列的第N个项的指令存储为Sequence
。这很方便,因为它允许我通过简单调用Func<int, int>
来调用NTerm(int n)
并使用lambda创建Func
。我想避免改变这种方法。
我想基于两个Sequence
的相等性来检查两个Sequence对象的相等性。我开始浏览,并且有一些帖子使用Func
来分解lambdas和Expression
s以获得平等,但我在谈论数学上的平等。
换句话说,
Func
应该等于x => 2 * x
,以及数学表达式的任何变体,例如Math.Pow或更多涉及的运算符。如果我可以让它工作,我可以比较c => c * 2
s的数学平等。
我尝试编写自己的扩展方法:
Sequence
我不确定怎么去那里。我写了一些基本的默认值:
public static bool MathEquals(this Expression<Func<int, int>> f,
Expression<Func<int, int>> g)
但是我需要检查两个lambda表达式的数学相等性,即两个if (ReferenceEquals (f, g)) return true;
if (f == null || g == null) return false;
if (f.NodeType != g.NodeType || f.Type != g.Type) return false;
s。可以这样做吗?有没有人有办法解决吗?我是否需要更改存储第N项公式的方法?我反对检查输出,因为某些输出的序列可能相等而不是全部。
如果我需要发布任何序列代码,我会。
更新:我决定将斯科特的答案标记为已被接受。但是,工作还不完整。查看第二部分here。
答案 0 :(得分:2)
您的问题分为两部分,“如何分解表达式并对其进行分析”,以及“如何检查两个表达式是否表示相同的逻辑运算”。
我不知道如何做第二部分,但我知道第一部分。
您需要做的是创建一个ExpressionVisitor
,并通过覆盖VisitBinary
并构建所有操作的列表来遍历每个BinaryExpression
。
public class OperationParser : ExpressionVisitor
{
public OperationParser()
{
Expressions = new List<BinaryExpression>();
}
public List<BinaryExpression> Expressions { get; private set; }
protected override Expression VisitBinary(BinaryExpression b)
{
Expressions.Add(b);
return base.VisitBinary(b);
}
}
然后你会做
Expression<Func<int, int>> expression1 = (x) => x + 2;
Expression<Func<int, int>> expression2 = (y) => 2 + y;
var parser1 = new OperationParser();
parser1.Visit(expression1);
var parser2 = new OperationParser();
parser2.Visit(expression2);
//TODO: write a way to compare parser1.Expressions to parser2.Expressions to see if they "mean the same thig"
你只需要用“你的第二个问题”来填写TODO