我有一个Sequence
实现 ISequence
的类型。 ISequence
实现IEnumerable<Element>
哪里Element
是另一种自定义类型。目前,我的Sequence
type 将生成序列第 N 项的指令存储为 Func<int, int>
。这很方便,因为它允许我调用 NTerm(int n)
只需简单调用 Func
并创建Sequence
s 带有 lambda。我想避免改变这种方法。
我想根据两个 Func
的相等性来检查两个 Sequence 对象的相等性s。我开始浏览,有一些帖子使用 Expression
s 分解 lambda 和 Func
s 代表平等,但我说的是数学平等。
In other words,
x => 2 * x
should equalc => c * 2
, along with any variations of mathematical expressions, such as Math.Pow or more involved operators. If I can get that to work, I can compareSequence
s for mathematical equality.
我尝试编写自己的扩展方法:
public static bool MathEquals(this Expression<Func<int, int>> f,
Expression<Func<int, int>> g)
我不知道如何从那里开始。我写了一些基本的默认值:
if (ReferenceEquals (f, g)) return true;
if (f == null || g == null) return false;
if (f.NodeType != g.NodeType || f.Type != g.Type) return false;
但我需要检查两个 lambda 表达式的数学相等性,即两个 Func<int, int>
s。这可以做到吗?有没有人有办法解决吗?我是否需要更改存储第 N 项公式的方法?我反对检查输出,因为某些输出的序列可能相同,但并非全部输出相同。
如果我需要发布任何序列代码,我会的。
更新:我决定将 Scott 的回答标记为已接受。然而,工作尚未完成。查看第二部分here .
最佳答案
您的问题有两个部分,“如何分解表达式并对其进行评估”,以及“如何检查两个表达式是否表示相同的逻辑运算”。
我不知道如何做第二部分,但我知道第一部分。
您需要做的是创建一个 ExpressionVisitor
并让它遍历每个 BinaryExpression
通过重写 VisitBinary
并构建所有操作的列表。
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 中填写“您的第二个问题”即可
关于c# - Func<int, int> 的数学等式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31643934/