Func的数学平等<int,int =“”>

时间:2015-07-27 01:59:20

标签: c# math lambda extension-methods

我有一个实现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

1 个答案:

答案 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